summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rwxr-xr-xbin/syncqt2
-rwxr-xr-xconfigure26
-rw-r--r--configure.exebin856064 -> 1343488 bytes
-rw-r--r--demos/declarative/calculator/CalcButton.qml60
-rw-r--r--demos/declarative/calculator/calculator.js87
-rw-r--r--demos/declarative/calculator/calculator.qml127
-rw-r--r--demos/declarative/calculator/pics/button-pressed.pngbin0 -> 644 bytes
-rw-r--r--demos/declarative/calculator/pics/button-pressed.sci5
-rw-r--r--demos/declarative/calculator/pics/button.pngbin0 -> 635 bytes
-rw-r--r--demos/declarative/calculator/pics/button.sci5
-rw-r--r--demos/declarative/calculator/pics/clear.pngbin0 -> 611 bytes
-rw-r--r--demos/declarative/contacts/Button.qml57
-rw-r--r--demos/declarative/contacts/Contact.qml113
-rw-r--r--demos/declarative/contacts/ContactField.qml60
-rw-r--r--demos/declarative/contacts/FieldText.qml160
-rw-r--r--demos/declarative/contacts/RemoveButton.qml126
-rw-r--r--demos/declarative/contacts/SearchBar.qml24
-rw-r--r--demos/declarative/contacts/contacts.qml293
-rw-r--r--demos/declarative/contacts/contacts.sqlitebin0 -> 86016 bytes
-rw-r--r--demos/declarative/contacts/pics/cancel.pngbin0 -> 1038 bytes
-rw-r--r--demos/declarative/contacts/pics/email.pngbin0 -> 977 bytes
-rw-r--r--demos/declarative/contacts/pics/new.pngbin0 -> 688 bytes
-rw-r--r--demos/declarative/contacts/pics/ok.pngbin0 -> 655 bytes
-rw-r--r--demos/declarative/contacts/pics/phone.pngbin0 -> 624 bytes
-rw-r--r--demos/declarative/contacts/pics/search.pngbin0 -> 635 bytes
-rw-r--r--demos/declarative/contacts/pics/trash.pngbin0 -> 989 bytes
-rw-r--r--demos/declarative/flickr/content/ImageDetails.qml141
-rw-r--r--demos/declarative/flickr/content/LikeOMeter.qml33
-rw-r--r--demos/declarative/flickr/content/Loading.qml6
-rw-r--r--demos/declarative/flickr/content/MediaButton.qml39
-rw-r--r--demos/declarative/flickr/content/MediaLineEdit.qml109
-rw-r--r--demos/declarative/flickr/content/Progress.qml33
-rw-r--r--demos/declarative/flickr/content/ScrollBar.qml38
-rw-r--r--demos/declarative/flickr/content/Slider.qml34
-rw-r--r--demos/declarative/flickr/content/Star.qml44
-rw-r--r--demos/declarative/flickr/content/pics/background.pngbin0 -> 60504 bytes
-rw-r--r--demos/declarative/flickr/content/pics/button-pressed.pngbin0 -> 571 bytes
-rw-r--r--demos/declarative/flickr/content/pics/button-pressed.sci5
-rw-r--r--demos/declarative/flickr/content/pics/button.pngbin0 -> 564 bytes
-rw-r--r--demos/declarative/flickr/content/pics/button.sci5
-rw-r--r--demos/declarative/flickr/content/pics/ghns_star.pngbin0 -> 891 bytes
-rw-r--r--demos/declarative/flickr/content/pics/loading.pngbin0 -> 813 bytes
-rw-r--r--demos/declarative/flickr/content/pics/reflection.pngbin0 -> 4839 bytes
-rw-r--r--demos/declarative/flickr/content/pics/shadow-bottom.pngbin0 -> 656 bytes
-rw-r--r--demos/declarative/flickr/content/pics/shadow-corner.pngbin0 -> 405 bytes
-rw-r--r--demos/declarative/flickr/content/pics/shadow-right-screen.pngbin0 -> 227 bytes
-rw-r--r--demos/declarative/flickr/content/pics/shadow-right.pngbin0 -> 635 bytes
-rw-r--r--demos/declarative/flickr/flickr.qml208
-rw-r--r--demos/declarative/flickr/flickr2.qml263
-rw-r--r--demos/declarative/webbrowser/README6
-rw-r--r--demos/declarative/webbrowser/content/RectSoftShadow.qml30
-rw-r--r--demos/declarative/webbrowser/content/pics/addressbar-filled.pngbin0 -> 694 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/addressbar-filled.sci6
-rw-r--r--demos/declarative/webbrowser/content/pics/addressbar.pngbin0 -> 467 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/addressbar.sci6
-rw-r--r--demos/declarative/webbrowser/content/pics/back-disabled.pngbin0 -> 475 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/back.pngbin0 -> 707 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/footer.pngbin0 -> 200 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/footer.sci6
-rw-r--r--demos/declarative/webbrowser/content/pics/forward-disabled.pngbin0 -> 471 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/forward.pngbin0 -> 682 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/header.pngbin0 -> 193 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/reload.pngbin0 -> 1283 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/softshadow-bottom.pngbin0 -> 186 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/softshadow-left.pngbin0 -> 598 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/softshadow-left.sci5
-rw-r--r--demos/declarative/webbrowser/content/pics/softshadow-right.pngbin0 -> 636 bytes
-rw-r--r--demos/declarative/webbrowser/content/pics/softshadow-right.sci5
-rw-r--r--demos/declarative/webbrowser/content/pics/softshadow-top.pngbin0 -> 186 bytes
-rw-r--r--demos/declarative/webbrowser/webbrowser.qml429
-rw-r--r--doc/doc.pri5
-rw-r--r--doc/src/animation.qdoc2
-rw-r--r--doc/src/declarative/anchor-layout.qdoc68
-rw-r--r--doc/src/declarative/animation.qdoc169
-rw-r--r--doc/src/declarative/basictypes.qdoc265
-rw-r--r--doc/src/declarative/binding.qdoc110
-rw-r--r--doc/src/declarative/components.qdoc92
-rw-r--r--doc/src/declarative/cppitem.qdoc127
-rw-r--r--doc/src/declarative/effects.qdoc29
-rw-r--r--doc/src/declarative/elements.qdoc163
-rw-r--r--doc/src/declarative/examples.qdoc30
-rw-r--r--doc/src/declarative/focus.qdoc262
-rw-r--r--doc/src/declarative/measuring-performance.qdoc81
-rw-r--r--doc/src/declarative/modules.qdoc22
-rw-r--r--doc/src/declarative/pics/3d-axis.pngbin0 -> 13840 bytes
-rw-r--r--doc/src/declarative/pics/3d-rotation-axis.pngbin0 -> 14304 bytes
-rw-r--r--doc/src/declarative/pics/ListViewHighlight.pngbin0 -> 3582 bytes
-rw-r--r--doc/src/declarative/pics/ListViewHorizontal.pngbin0 -> 5802 bytes
-rw-r--r--doc/src/declarative/pics/ListViewSections.pngbin0 -> 7596 bytes
-rw-r--r--doc/src/declarative/pics/ListViewVertical.pngbin0 -> 2424 bytes
-rw-r--r--doc/src/declarative/pics/anchors.svg92
-rw-r--r--doc/src/declarative/pics/animatedimageitem.gifbin0 -> 9997 bytes
-rw-r--r--doc/src/declarative/pics/axisrotation.pngbin0 -> 3425 bytes
-rw-r--r--doc/src/declarative/pics/blur_example.pngbin0 -> 64019 bytes
-rw-r--r--doc/src/declarative/pics/content.pngbin0 -> 1978 bytes
-rw-r--r--doc/src/declarative/pics/declarative-qmlfocus1.pngbin0 -> 22047 bytes
-rw-r--r--doc/src/declarative/pics/declarative-qmlfocus2.pngbin0 -> 24225 bytes
-rw-r--r--doc/src/declarative/pics/declarative-qmlfocus3.pngbin0 -> 26300 bytes
-rw-r--r--doc/src/declarative/pics/declarative-qmlfocus4.pngbin0 -> 21401 bytes
-rw-r--r--doc/src/declarative/pics/edge1.pngbin0 -> 3423 bytes
-rw-r--r--doc/src/declarative/pics/edge2.pngbin0 -> 3436 bytes
-rw-r--r--doc/src/declarative/pics/edge3.pngbin0 -> 3854 bytes
-rw-r--r--doc/src/declarative/pics/edge4.pngbin0 -> 5152 bytes
-rw-r--r--doc/src/declarative/pics/edges.pngbin0 -> 15226 bytes
-rw-r--r--doc/src/declarative/pics/edges.svg185
-rw-r--r--doc/src/declarative/pics/edges_examples.svg109
-rw-r--r--doc/src/declarative/pics/edges_qml.pngbin0 -> 21731 bytes
-rw-r--r--doc/src/declarative/pics/edges_qml.svg188
-rw-r--r--doc/src/declarative/pics/flickable.gifbin0 -> 185221 bytes
-rw-r--r--doc/src/declarative/pics/flipable.gifbin0 -> 80659 bytes
-rw-r--r--doc/src/declarative/pics/gradient.pngbin0 -> 364 bytes
-rw-r--r--doc/src/declarative/pics/gridLayout_example.pngbin0 -> 437 bytes
-rw-r--r--doc/src/declarative/pics/gridview.pngbin0 -> 10564 bytes
-rw-r--r--doc/src/declarative/pics/highlight.gifbin0 -> 18259 bytes
-rw-r--r--doc/src/declarative/pics/horizontalLayout_example.pngbin0 -> 292 bytes
-rw-r--r--doc/src/declarative/pics/layout-add.gifbin0 -> 7821 bytes
-rw-r--r--doc/src/declarative/pics/layout-move.gifbin0 -> 6154 bytes
-rw-r--r--doc/src/declarative/pics/layout-remove.gifbin0 -> 5610 bytes
-rw-r--r--doc/src/declarative/pics/margins_qml.pngbin0 -> 18476 bytes
-rw-r--r--doc/src/declarative/pics/margins_qml.svg196
-rw-r--r--doc/src/declarative/pics/particles.gifbin0 -> 163068 bytes
-rw-r--r--doc/src/declarative/pics/pathview.gifbin0 -> 90512 bytes
-rw-r--r--doc/src/declarative/pics/propanim.gifbin0 -> 74909 bytes
-rw-r--r--doc/src/declarative/pics/qtlogo.pngbin0 -> 2738 bytes
-rw-r--r--doc/src/declarative/pics/reflection_example.pngbin0 -> 30919 bytes
-rw-r--r--doc/src/declarative/pics/repeater.pngbin0 -> 800 bytes
-rw-r--r--doc/src/declarative/pics/scalegrid.svg183
-rw-r--r--doc/src/declarative/pics/shadow_example.pngbin0 -> 4775 bytes
-rw-r--r--doc/src/declarative/pics/spacing_a.pngbin0 -> 495 bytes
-rw-r--r--doc/src/declarative/pics/spacing_b.pngbin0 -> 462 bytes
-rw-r--r--doc/src/declarative/pics/squish-transform.pngbin0 -> 9652 bytes
-rw-r--r--doc/src/declarative/pics/squish.pngbin0 -> 8590 bytes
-rw-r--r--doc/src/declarative/pics/trivialListView.pngbin0 -> 6160 bytes
-rw-r--r--doc/src/declarative/pics/verticalLayout_example.pngbin0 -> 385 bytes
-rw-r--r--doc/src/declarative/pics/verticalLayout_transition.gifbin0 -> 12641 bytes
-rw-r--r--doc/src/declarative/pics/webview.pngbin0 -> 126662 bytes
-rw-r--r--doc/src/declarative/qmlforcpp.qdoc724
-rw-r--r--doc/src/declarative/qmlintro.qdoc226
-rw-r--r--doc/src/declarative/qmlreference.qdoc42
-rw-r--r--doc/src/declarative/qmlviewer.qdoc75
-rw-r--r--doc/src/declarative/qtdeclarative.qdoc92
-rw-r--r--doc/src/declarative/qtprogrammers.qdoc124
-rw-r--r--doc/src/declarative/tutorial.qdoc19
-rw-r--r--doc/src/declarative/tutorial1.qdoc78
-rw-r--r--doc/src/declarative/tutorial2.qdoc132
-rw-r--r--doc/src/declarative/tutorial3.qdoc133
-rw-r--r--doc/src/images/declarative-anchors_example.pngbin0 -> 3654 bytes
-rw-r--r--doc/src/images/declarative-anchors_example2.pngbin0 -> 3819 bytes
-rw-r--r--doc/src/images/declarative-image_tile.pngbin0 -> 396 bytes
-rw-r--r--doc/src/images/declarative-item_opacity1.pngbin0 -> 464 bytes
-rw-r--r--doc/src/images/declarative-item_opacity2.pngbin0 -> 464 bytes
-rw-r--r--doc/src/images/declarative-item_stacking1.pngbin0 -> 460 bytes
-rw-r--r--doc/src/images/declarative-item_stacking2.pngbin0 -> 461 bytes
-rw-r--r--doc/src/images/declarative-item_stacking3.pngbin0 -> 464 bytes
-rw-r--r--doc/src/images/declarative-item_stacking4.pngbin0 -> 463 bytes
-rw-r--r--doc/src/images/declarative-nopercent.pngbin0 -> 553 bytes
-rw-r--r--doc/src/images/declarative-pathattribute.pngbin0 -> 7207 bytes
-rw-r--r--doc/src/images/declarative-pathcubic.pngbin0 -> 1261 bytes
-rw-r--r--doc/src/images/declarative-pathquad.pngbin0 -> 1517 bytes
-rw-r--r--doc/src/images/declarative-percent.pngbin0 -> 530 bytes
-rw-r--r--doc/src/images/declarative-qtlogo1.pngbin0 -> 3436 bytes
-rw-r--r--doc/src/images/declarative-qtlogo2.pngbin0 -> 11023 bytes
-rw-r--r--doc/src/images/declarative-qtlogo3.pngbin0 -> 5848 bytes
-rw-r--r--doc/src/images/declarative-qtlogo4.pngbin0 -> 11241 bytes
-rw-r--r--doc/src/images/declarative-rect.pngbin0 -> 674 bytes
-rw-r--r--doc/src/images/declarative-rect_gradient.pngbin0 -> 873 bytes
-rw-r--r--doc/src/images/declarative-rect_tint.pngbin0 -> 363 bytes
-rw-r--r--doc/src/images/declarative-removebutton-close.pngbin0 -> 3973 bytes
-rw-r--r--doc/src/images/declarative-removebutton-open.pngbin0 -> 5413 bytes
-rw-r--r--doc/src/images/declarative-removebutton.gifbin0 -> 183008 bytes
-rw-r--r--doc/src/images/declarative-removebutton.pngbin0 -> 6725 bytes
-rw-r--r--doc/src/images/declarative-reuse-1.pngbin0 -> 3489 bytes
-rw-r--r--doc/src/images/declarative-reuse-2.pngbin0 -> 3700 bytes
-rw-r--r--doc/src/images/declarative-reuse-3.pngbin0 -> 8829 bytes
-rw-r--r--doc/src/images/declarative-reuse-bluerect.pngbin0 -> 1474 bytes
-rw-r--r--doc/src/images/declarative-reuse-focus.pngbin0 -> 8026 bytes
-rw-r--r--doc/src/images/declarative-rotation.pngbin0 -> 645 bytes
-rw-r--r--doc/src/images/declarative-roundrect.pngbin0 -> 3058 bytes
-rw-r--r--doc/src/images/declarative-scale.pngbin0 -> 336 bytes
-rw-r--r--doc/src/images/declarative-scalegrid.pngbin0 -> 4228 bytes
-rw-r--r--doc/src/images/declarative-text.pngbin0 -> 3289 bytes
-rw-r--r--doc/src/images/declarative-textedit.gifbin0 -> 15286 bytes
-rw-r--r--doc/src/images/declarative-textformat.pngbin0 -> 11498 bytes
-rw-r--r--doc/src/images/declarative-textstyle.pngbin0 -> 6825 bytes
-rw-r--r--doc/src/images/declarative-transformorigin.pngbin0 -> 17468 bytes
-rw-r--r--doc/src/images/declarative-tutorial-list-closed.pngbin0 -> 11854 bytes
-rw-r--r--doc/src/images/declarative-tutorial-list-open.gifbin0 -> 877382 bytes
-rw-r--r--doc/src/images/declarative-tutorial-list-open.pngbin0 -> 14745 bytes
-rw-r--r--doc/src/images/declarative-tutorial-list.gifbin0 -> 3527095 bytes
-rw-r--r--doc/src/images/declarative-tutorial-list.pngbin0 -> 10723 bytes
-rw-r--r--doc/src/images/declarative-tutorial1.pngbin0 -> 3025 bytes
-rw-r--r--doc/src/images/declarative-tutorial2.pngbin0 -> 3050 bytes
-rw-r--r--doc/src/images/declarative-tutorial3_animation.gifbin0 -> 38111 bytes
-rw-r--r--doc/src/index.qdoc1
-rw-r--r--doc/src/modules.qdoc1
-rw-r--r--doc/src/qnamespace.qdoc2
-rw-r--r--doc/src/snippets/declarative/GroupBox.qml13
-rw-r--r--doc/src/snippets/declarative/comments.qml9
-rw-r--r--doc/src/snippets/declarative/content.qml7
-rw-r--r--doc/src/snippets/declarative/drag.qml16
-rw-r--r--doc/src/snippets/declarative/gradient.qml8
-rw-r--r--doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml23
-rw-r--r--doc/src/snippets/declarative/gridview/gridview.qml45
-rw-r--r--doc/src/snippets/declarative/gridview/pics/portrait.pngbin0 -> 3126 bytes
-rw-r--r--doc/src/snippets/declarative/listview/dummydata/ContactModel.qml15
-rw-r--r--doc/src/snippets/declarative/listview/highlight.qml49
-rw-r--r--doc/src/snippets/declarative/listview/listview.qml47
-rw-r--r--doc/src/snippets/declarative/mouseregion.qml23
-rw-r--r--doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml15
-rw-r--r--doc/src/snippets/declarative/pathview/pathattributes.qml34
-rw-r--r--doc/src/snippets/declarative/pathview/pathview.qml28
-rw-r--r--doc/src/snippets/declarative/pathview/pics/qtlogo-64.pngbin0 -> 2991 bytes
-rw-r--r--doc/src/snippets/declarative/pics/qt.pngbin0 -> 514 bytes
-rw-r--r--doc/src/snippets/declarative/repeater.qml12
-rw-r--r--doc/src/snippets/declarative/rotation.qml27
-rw-r--r--doc/src/snippets/qprocess-environment/main.cpp2
-rw-r--r--doc/src/topics.qdoc7
-rw-r--r--doc/src/tutorials/declarative.qdoc674
-rw-r--r--examples/declarative/animation/animation.qml51
-rw-r--r--examples/declarative/aspectratio/face_fit.qml26
-rw-r--r--examples/declarative/aspectratio/face_fit_animated.qml28
-rw-r--r--examples/declarative/aspectratio/pics/face.pngbin0 -> 905 bytes
-rw-r--r--examples/declarative/aspectratio/scale_and_crop.qml21
-rw-r--r--examples/declarative/aspectratio/scale_and_sidecrop.qml22
-rw-r--r--examples/declarative/aspectratio/scale_to_fit.qml21
-rw-r--r--examples/declarative/behaviours/MyRect.qml11
-rw-r--r--examples/declarative/behaviours/test.qml103
-rw-r--r--examples/declarative/connections/connections.qml29
-rw-r--r--examples/declarative/declarative.pro4
-rw-r--r--examples/declarative/dial/DialLibrary/Dial.qml34
-rw-r--r--examples/declarative/dial/DialLibrary/background.pngbin0 -> 35876 bytes
-rw-r--r--examples/declarative/dial/DialLibrary/needle.pngbin0 -> 342 bytes
-rw-r--r--examples/declarative/dial/DialLibrary/needle_shadow.pngbin0 -> 632 bytes
-rw-r--r--examples/declarative/dial/DialLibrary/overlay.pngbin0 -> 3564 bytes
-rw-r--r--examples/declarative/dial/dial.qml31
-rw-r--r--examples/declarative/easing/easing.qml92
-rw-r--r--examples/declarative/follow/follow.qml50
-rw-r--r--examples/declarative/follow/pong.qml67
-rw-r--r--examples/declarative/listview/content/MediaButton.qml37
-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/moreDown.pngbin0 -> 217 bytes
-rw-r--r--examples/declarative/listview/content/pics/moreUp.pngbin0 -> 212 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.qml59
-rw-r--r--examples/declarative/listview/dummydata/Recipes.qml88
-rw-r--r--examples/declarative/listview/highlight.qml57
-rw-r--r--examples/declarative/listview/listview.qml80
-rw-r--r--examples/declarative/listview/recipes.qml133
-rw-r--r--examples/declarative/listview/sections.qml69
-rw-r--r--examples/declarative/minehunt/Description.qml36
-rw-r--r--examples/declarative/minehunt/Explosion.qml18
-rw-r--r--examples/declarative/minehunt/main.cpp312
-rw-r--r--examples/declarative/minehunt/minehunt.pro8
-rw-r--r--examples/declarative/minehunt/minehunt.qml160
-rw-r--r--examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpgbin0 -> 30730 bytes
-rw-r--r--examples/declarative/minehunt/pics/back.pngbin0 -> 558 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/face-sad.pngbin0 -> 14844 bytes
-rw-r--r--examples/declarative/minehunt/pics/face-smile-big.pngbin0 -> 13810 bytes
-rw-r--r--examples/declarative/minehunt/pics/face-smile.pngbin0 -> 15408 bytes
-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/front.pngbin0 -> 580 bytes
-rw-r--r--examples/declarative/minehunt/pics/star.pngbin0 -> 2677 bytes
-rw-r--r--examples/declarative/mouseregion/mouse.qml38
-rw-r--r--examples/declarative/scrollbar/ScrollBar.qml29
-rw-r--r--examples/declarative/scrollbar/display.qml63
-rw-r--r--examples/declarative/scrollbar/pics/niagara_falls.jpgbin0 -> 604121 bytes
-rw-r--r--examples/declarative/slideswitch/Switch.qml56
-rw-r--r--examples/declarative/slideswitch/background.svg23
-rw-r--r--examples/declarative/slideswitch/display.qml8
-rw-r--r--examples/declarative/slideswitch/knob.svg867
-rw-r--r--examples/declarative/states/states.qml40
-rw-r--r--examples/declarative/states/transitions.qml60
-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/Removebutton.qml9
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml34
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml18
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml20
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml39
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml110
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml117
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml117
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml57
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml30
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml115
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml33
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml115
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml33
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml117
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml32
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml123
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml37
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml47
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml61
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml148
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml119
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml50
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml58
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml149
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml123
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml57
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml44
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml126
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml139
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml29
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml57
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/Button.qml57
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml46
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml58
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml149
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml121
-rwxr-xr-xexamples/declarative/tutorials/contacts/shared/contactGenSQL.pl82
-rw-r--r--examples/declarative/tutorials/contacts/shared/contacts.sqlitebin0 -> 86016 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/email.txt7
-rw-r--r--examples/declarative/tutorials/contacts/shared/english-f.txt143
-rw-r--r--examples/declarative/tutorials/contacts/shared/english-m.txt130
-rw-r--r--examples/declarative/tutorials/contacts/shared/english-s.txt1003
-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/helloworld/t1/tutorial1.qml14
-rw-r--r--examples/declarative/tutorials/helloworld/t2/Cell.qml16
-rw-r--r--examples/declarative/tutorials/helloworld/t2/tutorial2.qml27
-rw-r--r--examples/declarative/tutorials/helloworld/t3/Cell.qml15
-rw-r--r--examples/declarative/tutorials/helloworld/t3/tutorial3.qml59
-rw-r--r--examples/declarative/velocity/Day.qml111
-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.qml113
-rw-r--r--examples/declarative/webview/autosize.qml59
-rw-r--r--examples/declarative/webview/content/SpinSquare.qml24
-rw-r--r--examples/declarative/webview/inline-html.qml12
-rw-r--r--examples/declarative/webview/qml-in-html.qml30
-rw-r--r--examples/declarative/webview/transparent.qml11
-rw-r--r--examples/declarative/xmldata/daringfireball.qml59
-rw-r--r--examples/declarative/xmldata/yahoonews.qml113
-rw-r--r--examples/examples.pro1
-rw-r--r--mkspecs/features/qt.prf3
-rw-r--r--mkspecs/linux-g++-x11egl/qmake.conf26
-rw-r--r--mkspecs/linux-g++-x11egl/qplatformdefs.h134
-rw-r--r--mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf20
-rw-r--r--mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h42
-rw-r--r--src/3rdparty/easing/legal.qdoc2
-rw-r--r--src/corelib/animation/qabstractanimation.cpp2
-rw-r--r--src/corelib/animation/qvariantanimation.cpp4
-rw-r--r--src/corelib/codecs/qtextcodec.cpp4
-rw-r--r--src/corelib/global/qglobal.h13
-rw-r--r--src/corelib/kernel/kernel.pri4
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp34
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h3
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h5
-rw-r--r--src/corelib/kernel/qcoreevent.cpp2
-rw-r--r--src/corelib/kernel/qcoreevent.h1
-rw-r--r--src/corelib/kernel/qmetaobject.cpp89
-rw-r--r--src/corelib/kernel/qmetaobject.h3
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp2446
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h269
-rw-r--r--src/corelib/kernel/qobject.cpp17
-rw-r--r--src/corelib/kernel/qobject.h11
-rw-r--r--src/corelib/kernel/qobject_p.h20
-rw-r--r--src/corelib/kernel/qobjectdefs.h4
-rw-r--r--src/corelib/kernel/qvariant_p.h2
-rw-r--r--src/declarative/3rdparty/3rdparty.pri5
-rw-r--r--src/declarative/3rdparty/qlistmodelinterface.cpp108
-rw-r--r--src/declarative/3rdparty/qlistmodelinterface.h86
-rw-r--r--src/declarative/canvas/canvas.pri19
-rw-r--r--src/declarative/canvas/qsimplecanvas.cpp1029
-rw-r--r--src/declarative/canvas/qsimplecanvas.h173
-rw-r--r--src/declarative/canvas/qsimplecanvas_graphicsview.cpp213
-rw-r--r--src/declarative/canvas/qsimplecanvas_opengl.cpp474
-rw-r--r--src/declarative/canvas/qsimplecanvas_opengl1.cpp401
-rw-r--r--src/declarative/canvas/qsimplecanvas_p.h199
-rw-r--r--src/declarative/canvas/qsimplecanvas_software.cpp232
-rw-r--r--src/declarative/canvas/qsimplecanvasdebugplugin.cpp155
-rw-r--r--src/declarative/canvas/qsimplecanvasdebugplugin_p.h85
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter.cpp323
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter.h113
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter_p.h70
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.cpp1872
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.h304
-rw-r--r--src/declarative/canvas/qsimplecanvasitem_p.h266
-rw-r--r--src/declarative/debugger/debugger.pri17
-rw-r--r--src/declarative/debugger/qmldebugclient.cpp190
-rw-r--r--src/declarative/debugger/qmldebugclient.h96
-rw-r--r--src/declarative/debugger/qmldebugger.cpp355
-rw-r--r--src/declarative/debugger/qmldebugger.h104
-rw-r--r--src/declarative/debugger/qmldebuggerstatus.cpp54
-rw-r--r--src/declarative/debugger/qmldebuggerstatus.h67
-rw-r--r--src/declarative/debugger/qmldebugserver.cpp299
-rw-r--r--src/declarative/debugger/qmldebugserver.h82
-rw-r--r--src/declarative/debugger/qmlobjecttree.cpp75
-rw-r--r--src/declarative/debugger/qmlobjecttree_p.h86
-rw-r--r--src/declarative/debugger/qmlpropertyview.cpp224
-rw-r--r--src/declarative/debugger/qmlpropertyview_p.h78
-rw-r--r--src/declarative/debugger/qmlwatches.cpp304
-rw-r--r--src/declarative/debugger/qmlwatches_p.h100
-rw-r--r--src/declarative/debugger/qpacketprotocol.cpp462
-rw-r--r--src/declarative/debugger/qpacketprotocol.h81
-rw-r--r--src/declarative/declarative.pro31
-rw-r--r--src/declarative/extra/extra.pri24
-rw-r--r--src/declarative/extra/qfxintegermodel.cpp126
-rw-r--r--src/declarative/extra/qfxintegermodel.h86
-rw-r--r--src/declarative/extra/qmlnumberformatter.cpp215
-rw-r--r--src/declarative/extra/qmlnumberformatter.h92
-rw-r--r--src/declarative/extra/qmlsqlconnection.cpp437
-rw-r--r--src/declarative/extra/qmlsqlconnection.h117
-rw-r--r--src/declarative/extra/qmlsqlquery.cpp694
-rw-r--r--src/declarative/extra/qmlsqlquery.h143
-rw-r--r--src/declarative/extra/qmlxmllistmodel.cpp536
-rw-r--r--src/declarative/extra/qmlxmllistmodel.h150
-rw-r--r--src/declarative/extra/qnumberformat.cpp224
-rw-r--r--src/declarative/extra/qnumberformat.h172
-rw-r--r--src/declarative/fx/fx.pri95
-rw-r--r--src/declarative/fx/qfxanchors.cpp889
-rw-r--r--src/declarative/fx/qfxanchors.h197
-rw-r--r--src/declarative/fx/qfxanchors_p.h132
-rw-r--r--src/declarative/fx/qfxanimatedimageitem.cpp213
-rw-r--r--src/declarative/fx/qfxanimatedimageitem.h100
-rw-r--r--src/declarative/fx/qfxanimatedimageitem_p.h77
-rw-r--r--src/declarative/fx/qfxblendedimage.cpp297
-rw-r--r--src/declarative/fx/qfxblendedimage.h111
-rw-r--r--src/declarative/fx/qfxblurfilter.cpp467
-rw-r--r--src/declarative/fx/qfxblurfilter.h82
-rw-r--r--src/declarative/fx/qfxcomponentinstance.cpp152
-rw-r--r--src/declarative/fx/qfxcomponentinstance.h89
-rw-r--r--src/declarative/fx/qfxcomponentinstance_p.h76
-rw-r--r--src/declarative/fx/qfxcontentwrapper.cpp144
-rw-r--r--src/declarative/fx/qfxcontentwrapper.h90
-rw-r--r--src/declarative/fx/qfxcontentwrapper_p.h71
-rw-r--r--src/declarative/fx/qfxevents.cpp182
-rw-r--r--src/declarative/fx/qfxevents_p.h127
-rw-r--r--src/declarative/fx/qfxflickable.cpp1153
-rw-r--r--src/declarative/fx/qfxflickable.h195
-rw-r--r--src/declarative/fx/qfxflickable_p.h170
-rw-r--r--src/declarative/fx/qfxflipable.cpp348
-rw-r--r--src/declarative/fx/qfxflipable.h106
-rw-r--r--src/declarative/fx/qfxfocuspanel.cpp104
-rw-r--r--src/declarative/fx/qfxfocuspanel.h81
-rw-r--r--src/declarative/fx/qfxfocusrealm.cpp72
-rw-r--r--src/declarative/fx/qfxfocusrealm.h67
-rw-r--r--src/declarative/fx/qfxgridview.cpp1428
-rw-r--r--src/declarative/fx/qfxgridview.h148
-rw-r--r--src/declarative/fx/qfxhighlightfilter.cpp319
-rw-r--r--src/declarative/fx/qfxhighlightfilter.h98
-rw-r--r--src/declarative/fx/qfximage.cpp1015
-rw-r--r--src/declarative/fx/qfximage.h129
-rw-r--r--src/declarative/fx/qfximage_p.h119
-rw-r--r--src/declarative/fx/qfxitem.cpp2100
-rw-r--r--src/declarative/fx/qfxitem.h277
-rw-r--r--src/declarative/fx/qfxitem_p.h179
-rw-r--r--src/declarative/fx/qfxkeyactions.cpp920
-rw-r--r--src/declarative/fx/qfxkeyactions.h319
-rw-r--r--src/declarative/fx/qfxkeyproxy.cpp116
-rw-r--r--src/declarative/fx/qfxkeyproxy.h78
-rw-r--r--src/declarative/fx/qfxlayouts.cpp1082
-rw-r--r--src/declarative/fx/qfxlayouts.h171
-rw-r--r--src/declarative/fx/qfxlayouts_p.h100
-rw-r--r--src/declarative/fx/qfxlistview.cpp1649
-rw-r--r--src/declarative/fx/qfxlistview.h154
-rw-r--r--src/declarative/fx/qfxmouseregion.cpp580
-rw-r--r--src/declarative/fx/qfxmouseregion.h163
-rw-r--r--src/declarative/fx/qfxmouseregion_p.h110
-rw-r--r--src/declarative/fx/qfxpainteditem.cpp340
-rw-r--r--src/declarative/fx/qfxpainteditem.h97
-rw-r--r--src/declarative/fx/qfxpainteditem_p.h95
-rw-r--r--src/declarative/fx/qfxparticles.cpp1200
-rw-r--r--src/declarative/fx/qfxparticles.h240
-rw-r--r--src/declarative/fx/qfxpath.cpp868
-rw-r--r--src/declarative/fx/qfxpath.h257
-rw-r--r--src/declarative/fx/qfxpath_p.h79
-rw-r--r--src/declarative/fx/qfxpathview.cpp890
-rw-r--r--src/declarative/fx/qfxpathview.h136
-rw-r--r--src/declarative/fx/qfxpathview_p.h151
-rw-r--r--src/declarative/fx/qfxpixmap.cpp233
-rw-r--r--src/declarative/fx/qfxpixmap.h87
-rw-r--r--src/declarative/fx/qfxrect.cpp1005
-rw-r--r--src/declarative/fx/qfxrect.h193
-rw-r--r--src/declarative/fx/qfxrect_p.h109
-rw-r--r--src/declarative/fx/qfxreflectionfilter.cpp352
-rw-r--r--src/declarative/fx/qfxreflectionfilter.h96
-rw-r--r--src/declarative/fx/qfxrepeater.cpp356
-rw-r--r--src/declarative/fx/qfxrepeater.h89
-rw-r--r--src/declarative/fx/qfxrepeater_p.h81
-rw-r--r--src/declarative/fx/qfxscalegrid.cpp216
-rw-r--r--src/declarative/fx/qfxscalegrid.h119
-rw-r--r--src/declarative/fx/qfxshadowfilter.cpp214
-rw-r--r--src/declarative/fx/qfxshadowfilter.h86
-rw-r--r--src/declarative/fx/qfxtext.cpp950
-rw-r--r--src/declarative/fx/qfxtext.h153
-rw-r--r--src/declarative/fx/qfxtext_p.h137
-rw-r--r--src/declarative/fx/qfxtextedit.cpp938
-rw-r--r--src/declarative/fx/qfxtextedit.h211
-rw-r--r--src/declarative/fx/qfxtextedit_p.h109
-rw-r--r--src/declarative/fx/qfxtransform.cpp895
-rw-r--r--src/declarative/fx/qfxtransform.h319
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp771
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.h132
-rw-r--r--src/declarative/fx/qfxwebview.cpp1076
-rw-r--r--src/declarative/fx/qfxwebview.h216
-rw-r--r--src/declarative/fx/qfxwidgetcontainer.cpp108
-rw-r--r--src/declarative/fx/qfxwidgetcontainer.h81
-rw-r--r--src/declarative/opengl/glbasicshaders.cpp707
-rw-r--r--src/declarative/opengl/glbasicshaders.h244
-rw-r--r--src/declarative/opengl/glheaders.h49
-rw-r--r--src/declarative/opengl/glsave.cpp1
-rw-r--r--src/declarative/opengl/glsave.h111
-rw-r--r--src/declarative/opengl/gltexture.cpp322
-rw-r--r--src/declarative/opengl/gltexture.h116
-rw-r--r--src/declarative/opengl/opengl.pri20
-rw-r--r--src/declarative/qml/parser/javascript.g2879
-rw-r--r--src/declarative/qml/parser/javascriptast.cpp952
-rw-r--r--src/declarative/qml/parser/javascriptast_p.h2511
-rw-r--r--src/declarative/qml/parser/javascriptastfwd_p.h183
-rw-r--r--src/declarative/qml/parser/javascriptastvisitor.cpp58
-rw-r--r--src/declarative/qml/parser/javascriptastvisitor_p.h326
-rw-r--r--src/declarative/qml/parser/javascriptengine_p.cpp191
-rw-r--r--src/declarative/qml/parser/javascriptengine_p.h145
-rw-r--r--src/declarative/qml/parser/javascriptgrammar.cpp829
-rw-r--r--src/declarative/qml/parser/javascriptgrammar_p.h200
-rw-r--r--src/declarative/qml/parser/javascriptlexer.cpp1196
-rw-r--r--src/declarative/qml/parser/javascriptlexer_p.h269
-rw-r--r--src/declarative/qml/parser/javascriptmemorypool_p.h130
-rw-r--r--src/declarative/qml/parser/javascriptnodepool_p.h138
-rw-r--r--src/declarative/qml/parser/javascriptparser.cpp1716
-rw-r--r--src/declarative/qml/parser/javascriptparser_p.h207
-rw-r--r--src/declarative/qml/parser/javascriptprettypretty.cpp1334
-rw-r--r--src/declarative/qml/parser/javascriptprettypretty_p.h329
-rw-r--r--src/declarative/qml/parser/parser.pri22
-rw-r--r--src/declarative/qml/qml.h119
-rw-r--r--src/declarative/qml/qml.pri74
-rw-r--r--src/declarative/qml/qmlbasicscript.cpp853
-rw-r--r--src/declarative/qml/qmlbasicscript_p.h104
-rw-r--r--src/declarative/qml/qmlbindablevalue.cpp237
-rw-r--r--src/declarative/qml/qmlbindablevalue.h94
-rw-r--r--src/declarative/qml/qmlbindablevalue_p.h66
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp159
-rw-r--r--src/declarative/qml/qmlboundsignal_p.h104
-rw-r--r--src/declarative/qml/qmlclassfactory.cpp47
-rw-r--r--src/declarative/qml/qmlclassfactory_p.h63
-rw-r--r--src/declarative/qml/qmlcompiledcomponent.cpp96
-rw-r--r--src/declarative/qml/qmlcompiledcomponent_p.h79
-rw-r--r--src/declarative/qml/qmlcompiler.cpp1618
-rw-r--r--src/declarative/qml/qmlcompiler_p.h199
-rw-r--r--src/declarative/qml/qmlcomponent.cpp547
-rw-r--r--src/declarative/qml/qmlcomponent.h110
-rw-r--r--src/declarative/qml/qmlcomponent_p.h92
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp367
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h153
-rw-r--r--src/declarative/qml/qmlcontext.cpp500
-rw-r--r--src/declarative/qml/qmlcontext.h107
-rw-r--r--src/declarative/qml/qmlcontext_p.h104
-rw-r--r--src/declarative/qml/qmlcustomparser.cpp235
-rw-r--r--src/declarative/qml/qmlcustomparser_p.h113
-rw-r--r--src/declarative/qml/qmlcustomparser_p_p.h79
-rw-r--r--src/declarative/qml/qmldeclarativedata_p.h71
-rw-r--r--src/declarative/qml/qmldom.cpp1544
-rw-r--r--src/declarative/qml/qmldom.h277
-rw-r--r--src/declarative/qml/qmldom_p.h119
-rw-r--r--src/declarative/qml/qmlengine.cpp1558
-rw-r--r--src/declarative/qml/qmlengine.h111
-rw-r--r--src/declarative/qml/qmlengine_p.h291
-rw-r--r--src/declarative/qml/qmlerror.cpp228
-rw-r--r--src/declarative/qml/qmlerror.h82
-rw-r--r--src/declarative/qml/qmlexpression.h118
-rw-r--r--src/declarative/qml/qmlinfo.cpp99
-rw-r--r--src/declarative/qml/qmlinfo.h69
-rw-r--r--src/declarative/qml/qmlinstruction.cpp178
-rw-r--r--src/declarative/qml/qmlinstruction_p.h272
-rw-r--r--src/declarative/qml/qmllist.h127
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp1123
-rw-r--r--src/declarative/qml/qmlmetaproperty.h142
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h82
-rw-r--r--src/declarative/qml/qmlmetatype.cpp1162
-rw-r--r--src/declarative/qml/qmlmetatype.h288
-rw-r--r--src/declarative/qml/qmlparser.cpp353
-rw-r--r--src/declarative/qml/qmlparser_p.h290
-rw-r--r--src/declarative/qml/qmlparserstatus.cpp88
-rw-r--r--src/declarative/qml/qmlparserstatus.h76
-rw-r--r--src/declarative/qml/qmlprivate.cpp48
-rw-r--r--src/declarative/qml/qmlprivate.h359
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.cpp81
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.h79
-rw-r--r--src/declarative/qml/qmlproxymetaobject.cpp113
-rw-r--r--src/declarative/qml/qmlproxymetaobject_p.h85
-rw-r--r--src/declarative/qml/qmlrefcount.cpp66
-rw-r--r--src/declarative/qml/qmlrefcount_p.h69
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp860
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h108
-rw-r--r--src/declarative/qml/qmlstringconverters.cpp212
-rw-r--r--src/declarative/qml/qmlstringconverters_p.h68
-rw-r--r--src/declarative/qml/qmlvme.cpp993
-rw-r--r--src/declarative/qml/qmlvme_p.h71
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp174
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h75
-rw-r--r--src/declarative/qml/rewriter/rewriter.cpp96
-rw-r--r--src/declarative/qml/rewriter/rewriter.pri9
-rw-r--r--src/declarative/qml/rewriter/rewriter_p.h151
-rw-r--r--src/declarative/qml/rewriter/textwriter.cpp217
-rw-r--r--src/declarative/qml/rewriter/textwriter_p.h99
-rw-r--r--src/declarative/test/qfxtestengine.cpp463
-rw-r--r--src/declarative/test/qfxtestengine.h85
-rw-r--r--src/declarative/test/qfxtestobjects.cpp354
-rw-r--r--src/declarative/test/qfxtestobjects.h212
-rw-r--r--src/declarative/test/qfxtestview.cpp82
-rw-r--r--src/declarative/test/qfxtestview.h74
-rw-r--r--src/declarative/test/test.pri9
-rw-r--r--src/declarative/timeline/qmltimeline.cpp940
-rw-r--r--src/declarative/timeline/qmltimeline.h190
-rw-r--r--src/declarative/timeline/qmltimelinevalueproxy.h86
-rw-r--r--src/declarative/timeline/timeline.pri7
-rw-r--r--src/declarative/util/qbindablemap.cpp182
-rw-r--r--src/declarative/util/qbindablemap.h87
-rw-r--r--src/declarative/util/qfxglobal.h124
-rw-r--r--src/declarative/util/qfxperf.cpp67
-rw-r--r--src/declarative/util/qfxperf.h81
-rw-r--r--src/declarative/util/qfxview.cpp570
-rw-r--r--src/declarative/util/qfxview.h114
-rw-r--r--src/declarative/util/qmlanimation.cpp2267
-rw-r--r--src/declarative/util/qmlanimation.h453
-rw-r--r--src/declarative/util/qmlanimation_p.h396
-rw-r--r--src/declarative/util/qmlbehaviour.cpp253
-rw-r--r--src/declarative/util/qmlbehaviour.h97
-rw-r--r--src/declarative/util/qmlbind.cpp203
-rw-r--r--src/declarative/util/qmlbind.h89
-rw-r--r--src/declarative/util/qmlconnection.cpp299
-rw-r--r--src/declarative/util/qmlconnection.h91
-rw-r--r--src/declarative/util/qmldatetimeformatter.cpp368
-rw-r--r--src/declarative/util/qmldatetimeformatter.h116
-rw-r--r--src/declarative/util/qmlfollow.cpp359
-rw-r--r--src/declarative/util/qmlfollow.h103
-rw-r--r--src/declarative/util/qmlfont.cpp147
-rw-r--r--src/declarative/util/qmlfont.h92
-rw-r--r--src/declarative/util/qmllistaccessor.cpp243
-rw-r--r--src/declarative/util/qmllistaccessor.h82
-rw-r--r--src/declarative/util/qmllistmodel.cpp570
-rw-r--r--src/declarative/util/qmllistmodel.h66
-rw-r--r--src/declarative/util/qmlnullablevalue_p.h67
-rw-r--r--src/declarative/util/qmlopenmetaobject.cpp211
-rw-r--r--src/declarative/util/qmlopenmetaobject.h89
-rw-r--r--src/declarative/util/qmlpackage.cpp153
-rw-r--r--src/declarative/util/qmlpackage.h87
-rw-r--r--src/declarative/util/qmlscript.cpp230
-rw-r--r--src/declarative/util/qmlscript.h80
-rw-r--r--src/declarative/util/qmlsetproperties.cpp362
-rw-r--r--src/declarative/util/qmlsetproperties.h80
-rw-r--r--src/declarative/util/qmlstate.cpp472
-rw-r--r--src/declarative/util/qmlstate.h175
-rw-r--r--src/declarative/util/qmlstate_p.h78
-rw-r--r--src/declarative/util/qmlstategroup.cpp306
-rw-r--r--src/declarative/util/qmlstategroup.h95
-rw-r--r--src/declarative/util/qmlstateoperations.cpp432
-rw-r--r--src/declarative/util/qmlstateoperations.h132
-rw-r--r--src/declarative/util/qmltransition.cpp285
-rw-r--r--src/declarative/util/qmltransition.h97
-rw-r--r--src/declarative/util/qperformancelog.cpp177
-rw-r--r--src/declarative/util/qperformancelog.h136
-rw-r--r--src/declarative/util/util.pri49
-rw-r--r--src/declarative/widgets/graphicslayouts.cpp323
-rw-r--r--src/declarative/widgets/graphicslayouts.h190
-rw-r--r--src/declarative/widgets/graphicswidgets.cpp173
-rw-r--r--src/declarative/widgets/graphicswidgets.h60
-rw-r--r--src/declarative/widgets/widgets.pri10
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h1
-rw-r--r--src/gui/graphicsview/qgraphicslayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp54
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h1
-rw-r--r--src/gui/kernel/qaction.h30
-rw-r--r--src/gui/kernel/qevent.cpp41
-rw-r--r--src/gui/kernel/qevent.h5
-rw-r--r--src/gui/kernel/qevent_p.h6
-rw-r--r--src/gui/kernel/qwidget.cpp4
-rw-r--r--src/gui/math3d/qgenericmatrix.cpp2
-rw-r--r--src/gui/painting/qdrawhelper.cpp4
-rw-r--r--src/gui/painting/qdrawutil.cpp39
-rw-r--r--src/gui/painting/qpainterpath.cpp2
-rw-r--r--src/gui/styles/qstyle.cpp1
-rw-r--r--src/gui/text/qtextcontrol_p.h2
-rw-r--r--src/gui/widgets/qbuttongroup.cpp13
-rw-r--r--src/script/qscriptextqobject.cpp2
-rw-r--r--src/src.pro4
-rw-r--r--src/testlib/qtestelementattribute.cpp40
-rw-r--r--src/tools/moc/generator.cpp22
-rw-r--r--src/tools/moc/keywords.cpp162
-rw-r--r--src/tools/moc/moc.cpp11
-rw-r--r--src/tools/moc/moc.h7
-rw-r--r--src/tools/moc/token.h1
-rw-r--r--src/tools/moc/util/generate_keywords.cpp1
-rw-r--r--src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp2
-rw-r--r--tests/auto/auto.pro4
-rw-r--r--tests/auto/declarative/.gitignore3
-rw-r--r--tests/auto/declarative/anchors/anchors.pro5
-rw-r--r--tests/auto/declarative/anchors/data/anchors.qml115
-rw-r--r--tests/auto/declarative/anchors/data/illegal1.qml10
-rw-r--r--tests/auto/declarative/anchors/data/illegal2.qml11
-rw-r--r--tests/auto/declarative/anchors/data/illegal3.qml10
-rw-r--r--tests/auto/declarative/anchors/data/loop1.qml6
-rw-r--r--tests/auto/declarative/anchors/data/loop2.qml18
-rw-r--r--tests/auto/declarative/anchors/tst_anchors.cpp166
-rw-r--r--tests/auto/declarative/datetimeformatter/datetimeformatter.pro3
-rw-r--r--tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp83
-rw-r--r--tests/auto/declarative/declarative.pro23
-rw-r--r--tests/auto/declarative/layouts/data/grid-margin.qml38
-rw-r--r--tests/auto/declarative/layouts/data/grid-spacing-margin.qml39
-rw-r--r--tests/auto/declarative/layouts/data/grid-spacing.qml38
-rw-r--r--tests/auto/declarative/layouts/data/grid.qml37
-rw-r--r--tests/auto/declarative/layouts/data/horizontal-margin.qml25
-rw-r--r--tests/auto/declarative/layouts/data/horizontal-spacing-margin.qml26
-rw-r--r--tests/auto/declarative/layouts/data/horizontal-spacing.qml25
-rw-r--r--tests/auto/declarative/layouts/data/horizontal.qml24
-rw-r--r--tests/auto/declarative/layouts/data/vertical-margin.qml25
-rw-r--r--tests/auto/declarative/layouts/data/vertical-spacing-margin.qml26
-rw-r--r--tests/auto/declarative/layouts/data/vertical-spacing.qml25
-rw-r--r--tests/auto/declarative/layouts/data/vertical.qml24
-rw-r--r--tests/auto/declarative/layouts/layouts.pro6
-rw-r--r--tests/auto/declarative/layouts/tst_layouts.cpp392
-rw-r--r--tests/auto/declarative/listview/data/listview.qml39
-rw-r--r--tests/auto/declarative/listview/listview.pro6
-rw-r--r--tests/auto/declarative/listview/tst_listview.cpp486
-rw-r--r--tests/auto/declarative/numberformatter/numberformatter.pro3
-rw-r--r--tests/auto/declarative/numberformatter/tst_numberformatter.cpp216
-rw-r--r--tests/auto/declarative/pathview/data/pathview.qml60
-rw-r--r--tests/auto/declarative/pathview/pathview.pro6
-rw-r--r--tests/auto/declarative/pathview/tst_pathview.cpp259
-rw-r--r--tests/auto/declarative/qbindablemap/qbindablemap.pro3
-rw-r--r--tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp72
-rw-r--r--tests/auto/declarative/qfxtext/qfxtext.pro3
-rw-r--r--tests/auto/declarative/qfxtext/tst_qfxtext.cpp413
-rw-r--r--tests/auto/declarative/qfxtextedit/qfxtextedit.pro3
-rw-r--r--tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp326
-rw-r--r--tests/auto/declarative/qmlbindengine/bindingLoop.txt12
-rw-r--r--tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.1.txt3
-rw-r--r--tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.2.txt3
-rw-r--r--tests/auto/declarative/qmlbindengine/idShortcutInvalidates.1.txt10
-rw-r--r--tests/auto/declarative/qmlbindengine/idShortcutInvalidates.txt9
-rw-r--r--tests/auto/declarative/qmlbindengine/methods.1.txt4
-rw-r--r--tests/auto/declarative/qmlbindengine/methods.2.txt4
-rw-r--r--tests/auto/declarative/qmlbindengine/qmlbindengine.pro9
-rw-r--r--tests/auto/declarative/qmlbindengine/signalAssignment.1.txt3
-rw-r--r--tests/auto/declarative/qmlbindengine/signalAssignment.2.txt3
-rw-r--r--tests/auto/declarative/qmlbindengine/testtypes.cpp4
-rw-r--r--tests/auto/declarative/qmlbindengine/testtypes.h127
-rw-r--r--tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp342
-rw-r--r--tests/auto/declarative/qmldom/qmldom.pro5
-rw-r--r--tests/auto/declarative/qmldom/tst_qmldom.cpp146
-rw-r--r--tests/auto/declarative/qmlengine/qmlengine.pro5
-rw-r--r--tests/auto/declarative/qmlengine/tst_qmlengine.cpp43
-rw-r--r--tests/auto/declarative/qmllist/qmllist.pro3
-rw-r--r--tests/auto/declarative/qmllist/tst_qmllist.cpp38
-rw-r--r--tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro3
-rw-r--r--tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp61
-rw-r--r--tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro3
-rw-r--r--tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp104
-rw-r--r--tests/auto/declarative/qmlparser/FailingComponent.qml3
-rw-r--r--tests/auto/declarative/qmlparser/MyComponent.qml4
-rw-r--r--tests/auto/declarative/qmlparser/MyContainerComponent.qml3
-rw-r--r--tests/auto/declarative/qmlparser/assignBasicTypes.txt25
-rw-r--r--tests/auto/declarative/qmlparser/assignLiteralSignalProperty.txt3
-rw-r--r--tests/auto/declarative/qmlparser/assignObjectToSignal.txt3
-rw-r--r--tests/auto/declarative/qmlparser/assignObjectToVariant.txt4
-rw-r--r--tests/auto/declarative/qmlparser/assignQmlComponent.txt3
-rw-r--r--tests/auto/declarative/qmlparser/assignSignal.txt3
-rw-r--r--tests/auto/declarative/qmlparser/assignTypeExtremes.txt4
-rw-r--r--tests/auto/declarative/qmlparser/attachedProperties.txt3
-rw-r--r--tests/auto/declarative/qmlparser/autoComponentCreation.txt3
-rw-r--r--tests/auto/declarative/qmlparser/customParserTypes.txt4
-rw-r--r--tests/auto/declarative/qmlparser/customVariantTypes.txt3
-rw-r--r--tests/auto/declarative/qmlparser/duplicateIDs.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/duplicateIDs.txt5
-rw-r--r--tests/auto/declarative/qmlparser/dynamicObject.1.txt6
-rw-r--r--tests/auto/declarative/qmlparser/dynamicProperties.txt11
-rw-r--r--tests/auto/declarative/qmlparser/dynamicSignalsAndSlots.txt6
-rw-r--r--tests/auto/declarative/qmlparser/empty.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/empty.txt0
-rw-r--r--tests/auto/declarative/qmlparser/failingComponent.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/failingComponent.txt4
-rw-r--r--tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/fakeDotProperty.txt3
-rw-r--r--tests/auto/declarative/qmlparser/idProperty.txt7
-rw-r--r--tests/auto/declarative/qmlparser/inlineQmlComponents.txt8
-rw-r--r--tests/auto/declarative/qmlparser/interfaceProperty.txt3
-rw-r--r--tests/auto/declarative/qmlparser/interfaceQList.txt6
-rw-r--r--tests/auto/declarative/qmlparser/interfaceQmlList.txt6
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.2.txt4
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.3.txt4
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.4.txt5
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.txt3
-rw-r--r--tests/auto/declarative/qmlparser/listAssignment.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/listAssignment.1.txt3
-rw-r--r--tests/auto/declarative/qmlparser/listAssignment.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/listAssignment.2.txt3
-rw-r--r--tests/auto/declarative/qmlparser/listAssignment.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/listAssignment.3.txt5
-rw-r--r--tests/auto/declarative/qmlparser/missingObject.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/missingObject.txt1
-rw-r--r--tests/auto/declarative/qmlparser/missingSignal.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/missingSignal.txt3
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.1.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.2.txt3
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.3.txt3
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.4.txt3
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.5.txt3
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.6.txt3
-rw-r--r--tests/auto/declarative/qmlparser/nullDotProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/nullDotProperty.txt3
-rw-r--r--tests/auto/declarative/qmlparser/propertyValueSource.txt3
-rw-r--r--tests/auto/declarative/qmlparser/qmlparser.pro9
-rw-r--r--tests/auto/declarative/qmlparser/readOnly.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/readOnly.1.txt3
-rw-r--r--tests/auto/declarative/qmlparser/readOnly.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/readOnly.2.txt3
-rw-r--r--tests/auto/declarative/qmlparser/rootAsQmlComponent.txt5
-rw-r--r--tests/auto/declarative/qmlparser/simpleBindings.txt17
-rw-r--r--tests/auto/declarative/qmlparser/simpleContainer.txt4
-rw-r--r--tests/auto/declarative/qmlparser/simpleObject.txt1
-rw-r--r--tests/auto/declarative/qmlparser/testtypes.cpp9
-rw-r--r--tests/auto/declarative/qmlparser/testtypes.h391
-rw-r--r--tests/auto/declarative/qmlparser/tst_qmlparser.cpp440
-rw-r--r--tests/auto/declarative/qmlparser/unregisteredObject.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/unregisteredObject.txt1
-rw-r--r--tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/unsupportedProperty.txt3
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.1.txt3
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.10.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.10.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.11.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.11.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.12.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.12.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.13.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.13.txt3
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.14.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.14.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.2.txt3
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.3.txt3
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.4.txt3
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.5.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.6.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.7.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.7.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.8.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.8.txt4
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.9.errors.txt1
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.9.txt4
-rw-r--r--tests/auto/declarative/repeater/data/repeater.qml18
-rw-r--r--tests/auto/declarative/repeater/repeater.pro6
-rw-r--r--tests/auto/declarative/repeater/tst_repeater.cpp91
-rw-r--r--tests/auto/declarative/simplecanvasitem/data/test.qml58
-rw-r--r--tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro6
-rw-r--r--tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp79
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/basic1.qml25
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/data/raster/image0.pngbin0 -> 1737 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/test1
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/basic2.qml29
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/data/raster/image0.pngbin0 -> 1737 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/test1
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/basic3.qml27
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/data/raster/image0.pngbin0 -> 1737 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/test1
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/basic4.qml31
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/data/raster/image0.pngbin0 -> 1737 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/test1
-rw-r--r--tests/auto/declarative/visual/bindinganimation/bindinganimation.qml40
-rw-r--r--tests/auto/declarative/visual/bindinganimation/data/raster/image0.pngbin0 -> 817 bytes
-rw-r--r--tests/auto/declarative/visual/bindinganimation/data/raster/manifest.qml86
-rw-r--r--tests/auto/declarative/visual/bindinganimation/test1
-rw-r--r--tests/auto/declarative/visual/colorAnimation/colorAnimation.qml41
-rw-r--r--tests/auto/declarative/visual/colorAnimation/data/raster/image0.pngbin0 -> 607 bytes
-rw-r--r--tests/auto/declarative/visual/colorAnimation/data/raster/manifest.qml522
-rw-r--r--tests/auto/declarative/visual/colorAnimation/data/raster/manifest.xml522
-rw-r--r--tests/auto/declarative/visual/colorAnimation/manifest-play.xml73
-rw-r--r--tests/auto/declarative/visual/easing/easing.qml186
-rw-r--r--tests/auto/declarative/visual/easing/image0.pngbin0 -> 17530 bytes
-rw-r--r--tests/auto/declarative/visual/easing/manifest-play.xml23
-rw-r--r--tests/auto/declarative/visual/easing/manifest.xml23
-rw-r--r--tests/auto/declarative/visual/easing/pics/qtlogo.pngbin0 -> 2738 bytes
-rw-r--r--tests/auto/declarative/visual/flickable/Day.qml26
-rw-r--r--tests/auto/declarative/visual/flickable/cork.jpgbin0 -> 88766 bytes
-rw-r--r--tests/auto/declarative/visual/flickable/flickable.qml53
-rw-r--r--tests/auto/declarative/visual/flickable/image0.pngbin0 -> 360547 bytes
-rw-r--r--tests/auto/declarative/visual/flickable/manifest-fail.xml30
-rw-r--r--tests/auto/declarative/visual/flickable/manifest.xml190
-rw-r--r--tests/auto/declarative/visual/flipable/flipable.xml138
-rw-r--r--tests/auto/declarative/visual/flipable/image0.pngbin0 -> 6184 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/manifest-play.xml24
-rw-r--r--tests/auto/declarative/visual/flipable/manifest.xml24
-rw-r--r--tests/auto/declarative/visual/flipable/pics/arrow.pngbin0 -> 546 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/face.pngbin0 -> 10112 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo0.pngbin0 -> 10412 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo1.pngbin0 -> 11068 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo10.pngbin0 -> 12539 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo2.pngbin0 -> 11490 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo3.pngbin0 -> 11308 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo4.pngbin0 -> 11322 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo5.pngbin0 -> 11497 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo6.pngbin0 -> 11707 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo7.pngbin0 -> 11101 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo8.pngbin0 -> 11558 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo9.pngbin0 -> 10943 bytes
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/data/raster/image0.pngbin0 -> 3209 bytes
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/data/raster/manifest.qml1262
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/pauseAnimation.qml28
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.pngbin0 -> 2738 bytes
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/test1
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/data/raster/image0.pngbin0 -> 909 bytes
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/elide.qml33
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/basic1.qml26
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/data/raster/image0.pngbin0 -> 1287 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/basic2.qml30
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/data/raster/image0.pngbin0 -> 1287 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/basic3.qml28
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/data/raster/image0.pngbin0 -> 1287 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/data/raster/manifest.qml13
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/basic4.qml32
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/data/raster/image0.pngbin0 -> 1287 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/test1
-rwxr-xr-xtests/auto/declarative/visual/runtests.sh3
-rw-r--r--tests/auto/declarative/visual/tests11
-rw-r--r--tests/auto/declarative/visual/tst_visual.cpp74
-rw-r--r--tests/auto/declarative/visual/visual.pro5
-rw-r--r--tests/auto/declarative/visual/webview/autosize/data/raster/image0.pngbin0 -> 4820 bytes
-rw-r--r--tests/auto/declarative/visual/webview/autosize/data/raster/manifest.qml6
-rw-r--r--tests/auto/declarative/visual/webview/autosize/test1
-rw-r--r--tests/auto/dynamicobject/dynamicobject.pro6
-rw-r--r--tests/auto/dynamicobject/qdynamicmetaobject.cpp254
-rw-r--r--tests/auto/dynamicobject/qdynamicmetaobject.h47
-rw-r--r--tests/auto/dynamicobject/qmetaobjectbuilder.cpp2347
-rw-r--r--tests/auto/dynamicobject/qmetaobjectbuilder.h258
-rw-r--r--tests/auto/dynamicobject/tst_qobject.cpp325
-rw-r--r--tests/auto/qmake/testdata/bundle-spaces/some-file6
-rw-r--r--tests/benchmarks/benchmarks.pro10
-rw-r--r--tests/benchmarks/qmlpainting/qmlpainting.pro5
-rw-r--r--tests/benchmarks/qmlpainting/tst_qmlpainting.cpp696
-rw-r--r--tools/configure/configureapp.cpp12
-rw-r--r--tools/linguist/lupdate/lupdate.h1
-rw-r--r--tools/linguist/lupdate/lupdate.pro4
-rw-r--r--tools/linguist/lupdate/main.cpp5
-rw-r--r--tools/linguist/lupdate/qml.cpp240
-rw-r--r--tools/qdoc3/codemarker.cpp109
-rw-r--r--tools/qdoc3/codemarker.h12
-rw-r--r--tools/qdoc3/command.cpp44
-rw-r--r--tools/qdoc3/cppcodemarker.cpp224
-rw-r--r--tools/qdoc3/cppcodemarker.h5
-rw-r--r--tools/qdoc3/cppcodeparser.cpp282
-rw-r--r--tools/qdoc3/cppcodeparser.h15
-rw-r--r--tools/qdoc3/generator.cpp190
-rw-r--r--tools/qdoc3/generator.h5
-rw-r--r--tools/qdoc3/helpprojectwriter.cpp35
-rw-r--r--tools/qdoc3/htmlgenerator.cpp597
-rw-r--r--tools/qdoc3/htmlgenerator.h23
-rw-r--r--tools/qdoc3/jambiapiparser.cpp5
-rw-r--r--tools/qdoc3/node.cpp106
-rw-r--r--tools/qdoc3/node.h131
-rw-r--r--tools/qdoc3/pagegenerator.cpp59
-rw-r--r--tools/qdoc3/test/classic.css49
-rw-r--r--tools/qdoc3/test/qml.qdocconf77
-rw-r--r--tools/qdoc3/test/qt-build-docs.qdocconf3
-rw-r--r--tools/qdoc3/test/qt-cpp-ignore.qdocconf4
-rw-r--r--tools/qdoc3/test/qt-inc.qdocconf4
-rw-r--r--tools/qdoc3/test/qt.qdocconf3
-rw-r--r--tools/qdoc3/tree.cpp55
-rw-r--r--tools/qdoc3/webxmlgenerator.cpp4
-rw-r--r--tools/qmldebugger/canvasframerate.cpp304
-rw-r--r--tools/qmldebugger/canvasframerate.h24
-rw-r--r--tools/qmldebugger/canvasscene.cpp245
-rw-r--r--tools/qmldebugger/canvasscene.h39
-rw-r--r--tools/qmldebugger/main.cpp137
-rw-r--r--tools/qmldebugger/qmldebugger.pro10
-rw-r--r--tools/qmlviewer/main.cpp165
-rw-r--r--tools/qmlviewer/qmlviewer.cpp696
-rw-r--r--tools/qmlviewer/qmlviewer.h95
-rw-r--r--tools/qmlviewer/qmlviewer.pro12
-rw-r--r--tools/tools.pro1
1018 files changed, 127567 insertions, 545 deletions
diff --git a/.gitignore b/.gitignore
index 0de9563..9f4144a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,8 +12,11 @@ config.tests/*/*/*
!config.tests/*/*/*[.]*
config.tests/*/*/*[.]app
+callgrind.out.*
+pcviewer.cfg
*~
*.a
+*.la
*.core
*.moc
*.o
@@ -44,6 +47,7 @@ bin/Qt*.dll
bin/assistant*
bin/designer*
bin/dumpcpp*
+bin/duiviewer*
bin/idc*
bin/linguist*
bin/lrelease*
diff --git a/bin/syncqt b/bin/syncqt
index 7a9f1d3..cd99288 100755
--- a/bin/syncqt
+++ b/bin/syncqt
@@ -30,6 +30,7 @@ my %modules = ( # path to module name map
"QtSql" => "$basedir/src/sql",
"QtNetwork" => "$basedir/src/network",
"QtSvg" => "$basedir/src/svg",
+ "QtDeclarative" => "$basedir/src/declarative",
"QtScript" => "$basedir/src/script",
"QtScriptTools" => "$basedir/src/scripttools",
"Qt3Support" => "$basedir/src/qt3support",
@@ -682,6 +683,7 @@ foreach (@modules_to_sync) {
$master_contents .= "#include <QtGui/QtGui>\n" if("$_" eq "gui");
$master_contents .= "#include <QtNetwork/QtNetwork>\n" if("$_" eq "network");
$master_contents .= "#include <QtSvg/QtSvg>\n" if("$_" eq "svg");
+ $master_contents .= "#include <QtDeclarative/QtDeclarative>\n" if("$_" eq "declarative");
$master_contents .= "#include <QtScript/QtScript>\n" if("$_" eq "script");
$master_contents .= "#include <QtScriptTools/QtScriptTools>\n" if("$_" eq "scripttools");
$master_contents .= "#include <Qt3Support/Qt3Support>\n" if("$_" eq "qt3support");
diff --git a/configure b/configure
index 764840e..d909c2a 100755
--- a/configure
+++ b/configure
@@ -600,6 +600,7 @@ CFG_RELEASE_QMAKE=no
CFG_PHONON=auto
CFG_PHONON_BACKEND=yes
CFG_SVG=yes
+CFG_DECLARATIVE=yes
CFG_WEBKIT=auto # (yes|no|auto)
CFG_GFX_AVAILABLE="linuxfb transformed qvfb vnc multiscreen"
@@ -832,7 +833,7 @@ while [ "$#" -gt 0 ]; do
VAL=no
;;
#Qt style yes options
- -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xinput|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-svg|-webkit|-scripttools|-rpath|-force-pkg-config)
+ -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xinput|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-svg|-declarative|-webkit|-scripttools|-rpath|-force-pkg-config)
VAR=`echo $1 | sed "s,^-\(.*\),\1,"`
VAL=yes
;;
@@ -1726,6 +1727,17 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
fi
+ ;;
+ declarative)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "auto" ]; then
+ CFG_DECLARATIVE="yes"
+ else
+ if [ "$VAL" = "no" ]; then
+ CFG_DECLARATIVE="no"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ fi
;;
webkit)
if [ "$VAL" = "yes" ] || [ "$VAL" = "auto" ]; then
@@ -3078,7 +3090,7 @@ Usage: $relconf [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir
[-no-phonon] [-phonon] [-no-phonon-backend] [-phonon-backend]
[-no-openssl] [-openssl] [-openssl-linked]
[-no-gtkstyle] [-gtkstyle] [-no-svg] [-svg] [-no-webkit] [-webkit]
- [-no-scripttools] [-scripttools]
+ [-no-scripttools] [-scripttools] [-no-declarative] [-declarative]
[additional platform specific options (see below)]
@@ -3227,6 +3239,9 @@ fi
-no-scripttools .... Do not build the QtScriptTools module.
+ -scripttools ....... Build the QtScriptTools module.
+ -no-declarative .....Do not build the declarative module.
+ + -declarative ....... Build the declarative module.
+
-platform target ... The operating system and compiler you are building
on ($PLATFORM).
@@ -5983,6 +5998,12 @@ else
QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_SVG"
fi
+if [ "$CFG_DECLARATIVE" = "yes" ]; then
+ QT_CONFIG="$QT_CONFIG declarative"
+else
+ QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_DECLARATIVE"
+fi
+
if [ "$CFG_WEBKIT" = "auto" ]; then
CFG_WEBKIT="$canBuildWebKit"
fi
@@ -6872,6 +6893,7 @@ echo "QtXmlPatterns module $CFG_XMLPATTERNS"
echo "Phonon module ....... $CFG_PHONON"
echo "SVG module .......... $CFG_SVG"
echo "WebKit module ....... $CFG_WEBKIT"
+echo "Declarative module .. $CFG_DECLARATIVE"
echo "STL support ......... $CFG_STL"
echo "PCH support ......... $CFG_PRECOMPILE"
echo "MMX/3DNOW/SSE/SSE2.. ${CFG_MMX}/${CFG_3DNOW}/${CFG_SSE}/${CFG_SSE2}"
diff --git a/configure.exe b/configure.exe
index 9da5c60..4dca7c4 100644
--- a/configure.exe
+++ b/configure.exe
Binary files differ
diff --git a/demos/declarative/calculator/CalcButton.qml b/demos/declarative/calculator/CalcButton.qml
new file mode 100644
index 0000000..8203710
--- /dev/null
+++ b/demos/declarative/calculator/CalcButton.qml
@@ -0,0 +1,60 @@
+Item {
+ property string operation
+ property bool toggable : false
+ property bool toggled : false
+
+ id: Button; width: 50; height: 30
+
+ Script {
+ function buttonClicked(operation) {
+ if (Button.toggable == true) {
+ if (Button.toggled == true) {
+ Button.toggled = false;
+ Button.state = 'Toggled';
+ } else {
+ Button.toggled = true;
+ Button.state = '';
+ }
+ }
+ else
+ doOp(operation);
+ }
+ }
+
+ Image {
+ id: Image
+ source: "pics/button.sci"
+ width: Button.width; height: Button.height
+ }
+
+ Image {
+ id: ImagePressed
+ source: "pics/button-pressed.sci"
+ width: Button.width; height: Button.height
+ opacity: 0
+ }
+
+ Text {
+ anchors.centeredIn: Image
+ text: Button.operation
+ color: "white"
+ font.bold: true
+ }
+
+ MouseRegion {
+ id: MouseRegion
+ anchors.fill: Button
+ onClicked: { buttonClicked(Button.operation) }
+ }
+
+ states: [
+ State {
+ name: "Pressed"; when: MouseRegion.pressed == true
+ SetProperties { target: ImagePressed; opacity: 1 }
+ },
+ State {
+ name: "Toggled"; when: Button.toggled == true
+ SetProperties { target: ImagePressed; opacity: 1 }
+ }
+ ]
+}
diff --git a/demos/declarative/calculator/calculator.js b/demos/declarative/calculator/calculator.js
new file mode 100644
index 0000000..774b232
--- /dev/null
+++ b/demos/declarative/calculator/calculator.js
@@ -0,0 +1,87 @@
+
+var curVal = 0;
+var memory = 0;
+var lastOp = "";
+var timer = 0;
+
+function disabled(op) {
+ if (op == "." && CurNum.text.toString().search(/\./) != -1) {
+ return true;
+ } else if (op == "Sqrt" && CurNum.text.toString().search(/-/) != -1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function doOp(op) {
+ if (disabled(op)) {
+ return;
+ }
+
+ if (op.toString().length==1 && ((op >= "0" && op <= "9") || op==".") ) {
+ if (CurNum.text.toString().length >= 14)
+ return; // No arbitrary length numbers
+ if (lastOp.toString().length == 1 && ((lastOp >= "0" && lastOp <= "9") || lastOp==".") ) {
+ CurNum.text = CurNum.text + op.toString();
+ } else {
+ CurNum.text = op;
+ }
+ lastOp = op;
+ return;
+ }
+ lastOp = op;
+
+ // Pending operations
+ if (CurrentOperation.text == "+") {
+ CurNum.text = Number(CurNum.text.valueOf()) + Number(curVal.valueOf());
+ } else if (CurrentOperation.text == "-") {
+ CurNum.text = Number(curVal) - Number(CurNum.text.valueOf());
+ } else if (CurrentOperation.text == "x") {
+ CurNum.text = Number(curVal) * Number(CurNum.text.valueOf());
+ } else if (CurrentOperation.text == "/") {
+ CurNum.text = Number(Number(curVal) / Number(CurNum.text.valueOf())).toString();
+ } else if (CurrentOperation.text == "=") {
+ }
+
+ if (op == "+" || op == "-" || op == "x" || op == "/") {
+ CurrentOperation.text = op;
+ curVal = CurNum.text.valueOf();
+ return;
+ }
+ curVal = 0;
+ CurrentOperation.text = "";
+
+ // Immediate operations
+ if (op == "1/x") { // reciprocal
+ CurNum.text = (1 / CurNum.text.valueOf()).toString();
+ } else if (op == "^2") { // squared
+ CurNum.text = (CurNum.text.valueOf() * CurNum.text.valueOf()).toString();
+ } else if (op == "Abs") {
+ CurNum.text = (Math.abs(CurNum.text.valueOf())).toString();
+ } else if (op == "Int") {
+ CurNum.text = (Math.floor(CurNum.text.valueOf())).toString();
+ } else if (op == "+/-") { // plus/minus
+ CurNum.text = (CurNum.text.valueOf() * -1).toString();
+ } else if (op == "Sqrt") { // square root
+ CurNum.text = (Math.sqrt(CurNum.text.valueOf())).toString();
+ } else if (op == "MC") { // memory clear
+ memory = 0;
+ } else if (op == "M+") { // memory increment
+ memory += CurNum.text.valueOf();
+ } else if (op == "MR") { // memory recall
+ CurNum.text = memory.toString();
+ } else if (op == "MS") { // memory set
+ memory = CurNum.text.valueOf();
+ } else if (op == "Bksp") {
+ CurNum.text = CurNum.text.toString().slice(0, -1);
+ } else if (op == "C") {
+ CurNum.text = "0";
+ } else if (op == "AC") {
+ curVal = 0;
+ memory = 0;
+ lastOp = "";
+ CurNum.text ="0";
+ }
+}
+
diff --git a/demos/declarative/calculator/calculator.qml b/demos/declarative/calculator/calculator.qml
new file mode 100644
index 0000000..145435b
--- /dev/null
+++ b/demos/declarative/calculator/calculator.qml
@@ -0,0 +1,127 @@
+Rect {
+ id: MainWindow;
+ width: 320; height: 270; color: "black"
+
+ Script { source: "calculator.js" }
+
+ VerticalLayout {
+ spacing: 2; margin: 2
+
+ Rect {
+ id: Container
+ width: 316; height: 60; z: 2
+ pen.color: "white"; color: "#343434"
+
+ Text {
+ id: CurNum
+ font.bold: true; font.size: 16
+ color: "white"
+ anchors.right: Container.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: Container.verticalCenter
+ }
+
+ Text {
+ id: CurrentOperation
+ color: "white"
+ font.bold: true; font.size: 16
+ anchors.left: Container.left
+ anchors.leftMargin: 5
+ anchors.verticalCenter: Container.verticalCenter
+ }
+ }
+
+ Item {
+ width: 320; height: 30
+
+ CalcButton {
+ id: AdvancedCheckBox
+ x: 55; width: 206
+ operation: "Advanced Mode"
+ toggable: true
+ }
+ }
+
+ Item {
+ width: 320
+
+ Item {
+ id: BasicButtons
+ x: 55; width: 160; height: 160
+
+ CalcButton { operation: "Bksp"; id: Bksp; width: 67; opacity: 0 }
+ CalcButton { operation: "C"; id: C; width: 76 }
+ CalcButton { operation: "AC"; id: AC; x: 78; width: 76 }
+
+ GridLayout {
+ id: NumKeypad; y: 32; spacing: 2; columns: 3
+
+ CalcButton { operation: 7 }
+ CalcButton { operation: 8 }
+ CalcButton { operation: 9 }
+ CalcButton { operation: 4 }
+ CalcButton { operation: 5 }
+ CalcButton { operation: 6 }
+ CalcButton { operation: 1 }
+ CalcButton { operation: 2 }
+ CalcButton { operation: 3 }
+ }
+
+ HorizontalLayout {
+ y: 128; spacing: 2
+
+ CalcButton { operation: 0; width: 50 }
+ CalcButton { operation: "."; x: 77; width: 50 }
+ CalcButton { operation: "="; id: Equals; x: 77; width: 102 }
+ }
+
+ VerticalLayout {
+ id: SimpleOperations
+ x: 156; y: 0; spacing: 2
+
+ CalcButton { operation: "x" }
+ CalcButton { operation: "/" }
+ CalcButton { operation: "-" }
+ CalcButton { operation: "+" }
+ }
+ }
+
+ GridLayout {
+ id: AdvancedButtons
+ x: 350; spacing: 2; columns: 2; opacity: 0
+
+ CalcButton { operation: "Abs" }
+ CalcButton { operation: "Int" }
+ CalcButton { operation: "MC" }
+ CalcButton { operation: "Sqrt" }
+ CalcButton { operation: "MR" }
+ CalcButton { operation: "^2" }
+ CalcButton { operation: "MS" }
+ CalcButton { operation: "1/x" }
+ CalcButton { operation: "M+" }
+ CalcButton { operation: "+/-" }
+ }
+
+ }
+ }
+
+ states: [
+ State {
+ name: "Advanced"; when: AdvancedCheckBox.toggled == true
+ SetProperties { target: BasicButtons; x: 0 }
+ SetProperties { target: SimpleOperations; y: 32 }
+ SetProperties { target: Bksp; opacity: 1 }
+ SetProperties { target: C; x: 69; width: 67 }
+ SetProperties { target: AC; x: 138; width: 67 }
+ SetProperties { target: Equals; width: 50 }
+ SetProperties { target: AdvancedButtons; x: 210; opacity: 1 }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ NumericAnimation { properties: "x,y,width"; easing: "easeOutBounce"; duration: 500 }
+ NumericAnimation { properties: "opacity"; easing: "easeInOutQuad"; duration: 500 }
+ }
+ ]
+}
diff --git a/demos/declarative/calculator/pics/button-pressed.png b/demos/declarative/calculator/pics/button-pressed.png
new file mode 100644
index 0000000..1a24cee
--- /dev/null
+++ b/demos/declarative/calculator/pics/button-pressed.png
Binary files differ
diff --git a/demos/declarative/calculator/pics/button-pressed.sci b/demos/declarative/calculator/pics/button-pressed.sci
new file mode 100644
index 0000000..f3bc860
--- /dev/null
+++ b/demos/declarative/calculator/pics/button-pressed.sci
@@ -0,0 +1,5 @@
+gridLeft: 5
+gridTop: 5
+gridBottom: 5
+gridRight: 5
+imageFile: button-pressed.png
diff --git a/demos/declarative/calculator/pics/button.png b/demos/declarative/calculator/pics/button.png
new file mode 100644
index 0000000..88c8bf8
--- /dev/null
+++ b/demos/declarative/calculator/pics/button.png
Binary files differ
diff --git a/demos/declarative/calculator/pics/button.sci b/demos/declarative/calculator/pics/button.sci
new file mode 100644
index 0000000..b1c7929
--- /dev/null
+++ b/demos/declarative/calculator/pics/button.sci
@@ -0,0 +1,5 @@
+gridLeft: 5
+gridTop: 5
+gridBottom: 5
+gridRight: 5
+imageFile: button.png
diff --git a/demos/declarative/calculator/pics/clear.png b/demos/declarative/calculator/pics/clear.png
new file mode 100644
index 0000000..fb07a27c
--- /dev/null
+++ b/demos/declarative/calculator/pics/clear.png
Binary files differ
diff --git a/demos/declarative/contacts/Button.qml b/demos/declarative/contacts/Button.qml
new file mode 100644
index 0000000..d9f1236
--- /dev/null
+++ b/demos/declarative/contacts/Button.qml
@@ -0,0 +1,57 @@
+Item {
+ id: button
+ width: 30
+ height: 30
+ property var icon: ""
+ signal clicked
+ Rect {
+ id: buttonRect
+ anchors.fill: parent
+ color: "lightgreen"
+ radius: 5
+ Image {
+ id: iconImage
+ source: 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"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "pressed"
+ ColorAnimation {
+ duration: 200
+ }
+ },
+ Transition {
+ fromState: "pressed"
+ toState: "*"
+ ColorAnimation {
+ duration: 1000
+ }
+ }
+ ]
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+}
diff --git a/demos/declarative/contacts/Contact.qml b/demos/declarative/contacts/Contact.qml
new file mode 100644
index 0000000..50c9d1c
--- /dev/null
+++ b/demos/declarative/contacts/Contact.qml
@@ -0,0 +1,113 @@
+Item {
+ id: contactDetails
+ anchors.fill: parent
+
+ property var contactId: ""
+ property var label: ""
+ property var phone: ""
+ property var email: ""
+
+ onLabelChanged: { labelField.value = label }
+ onEmailChanged: { emailField.value = email }
+ onPhoneChanged: { phoneField.value = phone }
+
+ resources: [
+ SqlQuery {
+ id: updateContactQuery
+ connection: contactDatabase
+ query: "UPDATE contacts SET label = :l, email = :e, phone = :p WHERE recid = :r"
+ bindings: [
+ SqlBind {
+ name: ":r"
+ value: contactId
+ },
+ SqlBind {
+ name: ":l"
+ value: labelField.value
+ },
+ SqlBind {
+ name: ":e"
+ value: emailField.value
+ },
+ SqlBind {
+ name: ":p"
+ value: phoneField.value
+ }
+ ]
+ },
+ SqlQuery {
+ id: insertContactQuery
+ connection: contactDatabase
+ query: "INSERT INTO contacts (label, email, phone) VALUES(:l, :e, :p)"
+ bindings: [
+ SqlBind {
+ name: ":l"
+ value: labelField.value
+ },
+ SqlBind {
+ name: ":e"
+ value: emailField.value
+ },
+ SqlBind {
+ name: ":p"
+ value: phoneField.value
+ }
+ ]
+ },
+ SqlQuery {
+ id: removeContactQuery
+ connection: contactDatabase
+ query: "DELETE FROM contacts WHERE recid = :r"
+ bindings: SqlBind {
+ name: ":r"
+ value: contactId
+ }
+ }
+ ]
+ function refresh() {
+ labelField.value = label;
+ emailField.value = email;
+ phoneField.value = phone;
+ }
+ function update() {
+ updateContactQuery.exec();
+ }
+ function insert() {
+ insertContactQuery.exec();
+ }
+ function remove() {
+ removeContactQuery.exec();
+ }
+ 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: "pics/phone.png"
+ label: "Phone"
+ }
+ ContactField {
+ id: emailField
+ anchors.left: layout.left
+ anchors.leftMargin: 5
+ anchors.right: layout.right
+ anchors.rightMargin: 5
+ icon: "pics/email.png"
+ label: "Email"
+ }
+ }
+}
diff --git a/demos/declarative/contacts/ContactField.qml b/demos/declarative/contacts/ContactField.qml
new file mode 100644
index 0000000..003e723
--- /dev/null
+++ b/demos/declarative/contacts/ContactField.qml
@@ -0,0 +1,60 @@
+Item {
+ id: contactField
+ clip: true
+ height: 30
+ property var label: "Name"
+ property var icon: ""
+ property var value: ""
+ onValueChanged: { fieldText.text = contactField.value }
+ 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
+ onConfirmed: { contactField.value=fieldText.text }
+ }
+ Image {
+ anchors.right: fieldText.left
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ source: 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "width,rightMargin"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/FieldText.qml b/demos/declarative/contacts/FieldText.qml
new file mode 100644
index 0000000..eb18ef2
--- /dev/null
+++ b/demos/declarative/contacts/FieldText.qml
@@ -0,0 +1,160 @@
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "black"
+ property var text: ""
+ property var label: ""
+ onTextChanged: { reset() }
+ signal confirmed
+ resources: [
+ Script {
+
+ function edit() {
+ if (!contacts.mouseGrabbed) {
+ fieldText.state='editing';
+ contacts.mouseGrabbed=true;
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ }
+
+ }
+ ]
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/cancel.png"
+ opacity: 0
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "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: contactDetails.state == "editing" ? "#505050" : "#AAAAAA"
+ font.italic: true
+ font.bold: true
+ text: fieldText.label
+ opacity: textEdit.text == '' ? 1 : 0
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/RemoveButton.qml b/demos/declarative/contacts/RemoveButton.qml
new file mode 100644
index 0000000..59e3fcb
--- /dev/null
+++ b/demos/declarative/contacts/RemoveButton.qml
@@ -0,0 +1,126 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ contacts.mouseGrabbed=false;
+ } else {
+ if (!contacts.mouseGrabbed) {
+ removeButton.state = 'opened';
+ contacts.mouseGrabbed=true;
+ }
+ }
+ }
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle(); removeButton.confirmed.emit() }
+ }
+ }
+ 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
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/SearchBar.qml b/demos/declarative/contacts/SearchBar.qml
new file mode 100644
index 0000000..3ee2665
--- /dev/null
+++ b/demos/declarative/contacts/SearchBar.qml
@@ -0,0 +1,24 @@
+Rect {
+ id: searchBar
+ color: "white"
+ property var text: searchEdit.text
+ Image {
+ id: searchIcon
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/search.png"
+ }
+ TextEdit {
+ id: searchEdit
+ anchors.left: searchIcon.right
+ anchors.right: parent.right
+ anchors.leftMargin: 5
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ readOnly: false
+ wrap: false
+ focus: true
+ text: ""
+ }
+}
diff --git a/demos/declarative/contacts/contacts.qml b/demos/declarative/contacts/contacts.qml
new file mode 100644
index 0000000..b38e02e
--- /dev/null
+++ b/demos/declarative/contacts/contacts.qml
@@ -0,0 +1,293 @@
+Rect {
+ id: contacts
+ width: 240
+ height: 320
+ color: "black"
+ property var mode: "list"
+ property var mouseGrabbed: false
+ resources: [
+ SqlConnection {
+ id: contactDatabase
+ name: "qmlConnection"
+ driver: "QSQLITE"
+ databaseName: "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"
+ bindings: SqlBind {
+ name: ":searchTerm"
+ value: '%' + searchBar.text + '%'
+ }
+ },
+ 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
+ children: [
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: {
+ Details.qml = 'Contact.qml';
+ wrapper.state='opened';
+ contacts.mode = 'edit';
+ }
+ }
+ ]
+ }
+ Item {
+ id: Details
+ anchors.fill: wrapper
+ opacity: 0
+ Bind {
+ target: Details.qmlItem
+ property: "contactId"
+ value: model.recid
+ }
+ 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
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ duration: 500
+ properties: "yPosition,height,opacity"
+ }
+ }
+ ]
+ Connection {
+ sender: confirmEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened' && !contacts.mouseGrabbed) {
+ Details.qmlItem.update();
+ wrapper.state = '';
+ contacts.mode = 'list';
+ contactList.exec();
+ }
+
+ }
+ }
+ Connection {
+ sender: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened' && !contacts.mouseGrabbed) {
+ wrapper.state = '';
+ contacts.mode = 'list';
+ }
+
+ }
+ }
+ Connection {
+ sender: removeContactButton
+ signal: "confirmed()"
+ script: {
+ if (wrapper.state == 'opened' && !contacts.mouseGrabbed) {
+ Details.qmlItem.remove();
+ wrapper.state = '';
+ contacts.mode = 'list';
+ contactList.exec();
+ }
+
+ }
+ }
+ }
+ }
+ ]
+ Button {
+ id: newContactButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "pics/new.png"
+ onClicked: { newContactItem.refresh(); contacts.mode = 'new' }
+ opacity: contacts.mode == 'list' ? 1 : 0
+ }
+ Button {
+ id: confirmEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ icon: "pics/ok.png"
+ opacity: contacts.mode == 'list' || contacts.mouseGrabbed ? 0 : 1
+ }
+ Button {
+ id: cancelEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "pics/cancel.png"
+ opacity: contacts.mode == 'list' || contacts.mouseGrabbed ? 0 : 1
+ }
+ RemoveButton {
+ id: removeContactButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.horizontalCenter: parent.horizontalCenter
+ opacity: (contacts.mode == 'edit' && (!contacts.mouseGrabbed || removeContactButton.state =='opened')) ? 1 : 0
+ }
+ ListView {
+ id: contactListView
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: cancelEditButton.bottom
+ anchors.bottom: searchBarWrapper.bottom
+ clip: true
+ model: contactList
+ delegate: contactDelegate
+ focus: false
+ }
+ FocusRealm {
+ id: newContactWrapper
+ anchors.fill: contactListView
+ opacity: 0
+ focus: contacts.mode == 'new'
+ Contact {
+ id: newContactItem
+ anchors.fill: parent
+ }
+ }
+ Connection {
+ sender: confirmEditButton
+ signal: "clicked()"
+ script: {
+ if (contacts.mode == 'new' && contacts.mouseGrabbed != 'true') {
+ newContactItem.insert();
+ contacts.mode = 'list';
+ contactList.exec();
+ }
+ }
+ }
+ Connection {
+ sender: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (contacts.mode == 'new' && contacts.mouseGrabbed != 'true') {
+ contacts.mode = 'list';
+ }
+ }
+ }
+ FocusRealm {
+ id: searchBarWrapper
+ height: 30
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottomMargin: 0
+ focus: false
+ SearchBar {
+ id: searchBar
+ anchors.fill: parent
+ }
+ states: [
+ State {
+ name: "searchHidden"
+ when: searchBar.text == '' || contacts.mode != 'list'
+ SetProperty {
+ target: searchBarWrapper.anchors
+ property: "bottomMargin"
+ value: -30
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "*"
+ NumericAnimation {
+ property: "bottomMargin"
+ duration: 250
+ }
+ }
+ ]
+ }
+ KeyProxy {
+ focus: contacts.mode != 'new'
+ targets: { contacts.mode == "list" ? [searchBarWrapper, contactListView] : [contactListView]}
+ }
+ states: [
+ State {
+ name: "editNewState"
+ when: contacts.mode == 'new'
+ SetProperty {
+ target: contactListView
+ property: "opacity"
+ value: 0
+ }
+ SetProperty {
+ target: newContactWrapper
+ property: "opacity"
+ value: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "*"
+ NumericAnimation {
+ property: "opacity"
+ duration: 500
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/contacts.sqlite b/demos/declarative/contacts/contacts.sqlite
new file mode 100644
index 0000000..d33e0c7
--- /dev/null
+++ b/demos/declarative/contacts/contacts.sqlite
Binary files differ
diff --git a/demos/declarative/contacts/pics/cancel.png b/demos/declarative/contacts/pics/cancel.png
new file mode 100644
index 0000000..ecc9533
--- /dev/null
+++ b/demos/declarative/contacts/pics/cancel.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/email.png b/demos/declarative/contacts/pics/email.png
new file mode 100644
index 0000000..04b3865
--- /dev/null
+++ b/demos/declarative/contacts/pics/email.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/new.png b/demos/declarative/contacts/pics/new.png
new file mode 100644
index 0000000..c7ebac3
--- /dev/null
+++ b/demos/declarative/contacts/pics/new.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/ok.png b/demos/declarative/contacts/pics/ok.png
new file mode 100644
index 0000000..5795f04
--- /dev/null
+++ b/demos/declarative/contacts/pics/ok.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/phone.png b/demos/declarative/contacts/pics/phone.png
new file mode 100644
index 0000000..fc9c222
--- /dev/null
+++ b/demos/declarative/contacts/pics/phone.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/search.png b/demos/declarative/contacts/pics/search.png
new file mode 100644
index 0000000..cc74e69
--- /dev/null
+++ b/demos/declarative/contacts/pics/search.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/trash.png b/demos/declarative/contacts/pics/trash.png
new file mode 100644
index 0000000..2042595
--- /dev/null
+++ b/demos/declarative/contacts/pics/trash.png
Binary files differ
diff --git a/demos/declarative/flickr/content/ImageDetails.qml b/demos/declarative/flickr/content/ImageDetails.qml
new file mode 100644
index 0000000..ccc91cb
--- /dev/null
+++ b/demos/declarative/flickr/content/ImageDetails.qml
@@ -0,0 +1,141 @@
+Flipable {
+ id: Container
+
+ property var frontContainer: ContainerFront
+ property string photoTitle: ""
+ property string photoDescription: ""
+ property string photoTags: ""
+ property int photoWidth
+ property int photoHeight
+ property string photoType
+ property string photoAuthor
+ property string photoDate
+ property string photoUrl
+ property int rating: 2
+ property var prevScale: 1.0
+
+ signal closed
+
+ axis: Axis { startX: Container.width / 2; endX: Container.width / 2; endY: 1 }
+
+ front: Item {
+ id: ContainerFront; anchors.fill: Container
+
+ Rect {
+ anchors.fill: parent
+ color: "black"; opacity: 0.4
+ pen.color: "white"; pen.width: 2
+ }
+
+ MediaButton {
+ id: BackButton; x: 630; y: 370; text: "Back"
+ onClicked: { Container.closed.emit() }
+ }
+
+ MediaButton {
+ id: MoreButton; x: 530; y: 370; text: "View..."
+ onClicked: { Container.state='Back' }
+ }
+
+ Text { id: TitleText; style: "Raised"; styleColor: "black"; color: "white"; elide: "ElideRight"
+ x: 220; y: 30; width: parent.width - 240; text: Container.photoTitle; font.size: 22 }
+
+ LikeOMeter { x: 40; y: 250; rating: Container.rating }
+
+ Flickable { id: Flickable; x: 220; width: 480; height: 210; y: 130; clip: true
+ viewportWidth: 480; viewportHeight: DescriptionText.height
+
+ WebView { id: DescriptionText; width: parent.width
+ html: "<style TYPE=\"text/css\">body {color: white;} a:link {color: cyan; text-decoration: underline; }</style>" + Container.photoDescription }
+ }
+
+ Text { id: Size; color: "white"; width: 300; x: 40; y: 300
+ text: "<b>Size:</b> " + Container.photoWidth + 'x' + Container.photoHeight }
+ Text { id: Type; color: "white"; width: 300; x: 40; anchors.top: Size.bottom
+ text: "<b>Type:</b> " + Container.photoType }
+
+ Text { id: Author; color: "white"; width: 300; x: 220; y: 80
+ text: "<b>Author:</b> " + Container.photoAuthor }
+ Text { id: Date; color: "white"; width: 300; x: 220; anchors.top: Author.bottom
+ text: "<b>Published:</b> " + Container.photoDate }
+ Text { id: TagsLabel; color: "white"; x: 220; anchors.top: Date.bottom;
+ text: Container.photoTags == "" ? "" : "<b>Tags:</b> " }
+ Text { id: Tags; color: "white"; width: parent.width-x-20;
+ anchors.left: TagsLabel.right; anchors.top: Date.bottom;
+ elide: "ElideRight"; text: Container.photoTags }
+
+ ScrollBar { id: ScrollBar; x: 720; y: Flickable.y; width: 7; height: Flickable.height; opacity: 0;
+ flickableArea: Flickable; clip: true }
+ }
+
+ back: Item {
+ anchors.fill: Container
+
+ Rect { anchors.fill: parent; color: "black"; opacity: 0.4; pen.color: "white"; pen.width: 2 }
+
+ Progress { anchors.centeredIn: parent; width: 200; height: 18; progress: BigImage.progress; visible: BigImage.status }
+ Flickable {
+ id: Flick; width: Container.width - 10; height: Container.height - 10
+ x: 5; y: 5; clip: true;
+ viewportWidth: ImageContainer.width; viewportHeight: ImageContainer.height
+
+ Item {
+ id: ImageContainer
+ width: Math.max(BigImage.width * BigImage.scale, Flick.width);
+ height: Math.max(BigImage.height * BigImage.scale, Flick.height);
+
+ Image {
+ id: BigImage; source: Container.photoUrl; scale: Slider.value
+ // Center image if it is smaller than the flickable area.
+ x: ImageContainer.width > width*scale ? (ImageContainer.width - width*scale) / 2 : 0
+ y: ImageContainer.height > height*scale ? (ImageContainer.height - height*scale) / 2 : 0
+ onStatusChanged : {
+ // Default scale shows the entire image.
+ if (status == 0 && width != 0) {
+ Slider.minimum = Math.min(Flick.width / width, Flick.height / height);
+ prevScale = Math.min(Slider.minimum, 1);
+ Slider.value = prevScale;
+ }
+ }
+ }
+ }
+ }
+
+ MediaButton {
+ id: BackButton2; x: 630; y: 370; text: "Back"; onClicked: { Container.state = '' }
+ }
+ Text {
+ text: "Image Unavailable"
+ visible: BigImage.status == 'Error'
+ anchors.centeredIn: parent; color: "white"; font.bold: true
+ }
+
+ Slider {
+ id: Slider; x: 25; y: 374; visible: { BigImage.status == 0 && maximum > minimum }
+ onValueChanged: {
+ if (BigImage.width * value > Flick.width) {
+ var xoff = (Flick.width/2 + Flick.xPosition) * value / prevScale;
+ Flick.xPosition = xoff - Flick.width/2;
+ }
+ if (BigImage.height * value > Flick.height) {
+ var yoff = (Flick.height/2 + Flick.yPosition) * value / prevScale;
+ Flick.yPosition = yoff - Flick.height/2;
+ }
+ prevScale = value;
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "Back"
+ SetProperty { target: Container; property: "rotation"; value: 180 }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ NumericAnimation { easing: "easeInOutQuad"; properties: "rotation"; duration: 500 }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/content/LikeOMeter.qml b/demos/declarative/flickr/content/LikeOMeter.qml
new file mode 100644
index 0000000..61317ae
--- /dev/null
+++ b/demos/declarative/flickr/content/LikeOMeter.qml
@@ -0,0 +1,33 @@
+Item {
+ id: Container
+
+ property int rating: 2
+
+ HorizontalLayout {
+ Star {
+ rating: 0
+ onClicked: { Container.rating = rating }
+ on: Container.rating >= 0
+ }
+ Star {
+ rating: 1
+ onClicked: { Container.rating = rating }
+ on: Container.rating >= 1
+ }
+ Star {
+ rating: 2
+ onClicked: { Container.rating = rating }
+ on: Container.rating >= 2
+ }
+ Star {
+ rating: 3
+ onClicked: { Container.rating = rating }
+ on: Container.rating >= 3
+ }
+ Star {
+ rating: 4
+ onClicked: { Container.rating = rating }
+ on: Container.rating >= 4
+ }
+ }
+}
diff --git a/demos/declarative/flickr/content/Loading.qml b/demos/declarative/flickr/content/Loading.qml
new file mode 100644
index 0000000..cf27e38
--- /dev/null
+++ b/demos/declarative/flickr/content/Loading.qml
@@ -0,0 +1,6 @@
+Image {
+ id: Loading; source: "pics/loading.png"; transformOrigin: "Center"
+ rotation: NumericAnimation {
+ id: "RotationAnimation"; from: 0; to: 360; running:true; repeat: true; duration: 900
+ }
+}
diff --git a/demos/declarative/flickr/content/MediaButton.qml b/demos/declarative/flickr/content/MediaButton.qml
new file mode 100644
index 0000000..6392a13
--- /dev/null
+++ b/demos/declarative/flickr/content/MediaButton.qml
@@ -0,0 +1,39 @@
+Item {
+ id: Container
+
+ signal clicked
+
+ property string text
+
+ Image {
+ id: Image
+ source: "pics/button.png"
+ }
+ Image {
+ id: Pressed
+ source: "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
+ states: [
+ State {
+ name: "Pressed"
+ when: MouseRegion.pressed == true
+ SetProperties {
+ target: Pressed
+ opacity: 1
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/content/MediaLineEdit.qml b/demos/declarative/flickr/content/MediaLineEdit.qml
new file mode 100644
index 0000000..691bb5b
--- /dev/null
+++ b/demos/declarative/flickr/content/MediaLineEdit.qml
@@ -0,0 +1,109 @@
+Item {
+ id: Container
+
+ property string label
+ property string text
+
+ width: Math.max(94,Label.width + Editor.width + 20)
+ height: Image.height
+
+ states: [
+ State {
+ name: "Edit"
+ SetProperties {
+ target: Label
+ text: Container.label + ": "
+ }
+ SetProperty {
+ target: Label
+ property: "x"
+ binding: 10
+ }
+ SetProperties {
+ target: Editor
+ cursorVisible: true
+ width: 100
+ }
+ SetProperties {
+ target: Proxy
+ focus: true
+ }
+ RunScript {
+ script:"Editor.selectAll()"
+ }
+ },
+ State {
+ // When returning to default state, typed text is propagated
+ RunScript {
+ script: "Container.text = Editor.text"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation { properties: "x,width"; duration: 500; easing: "easeInOutQuad" }
+ }
+ ]
+
+
+ Image {
+ id: Image
+ source: "pics/button.sci"
+ anchors.left: Container.left
+ anchors.right: Container.right
+ }
+
+ Image {
+ id: Pressed
+ source: "pics/button-pressed.sci"
+ opacity: 0
+ anchors.left: Container.left
+ anchors.right: Container.right
+ }
+
+ MouseRegion {
+ id: MouseRegion
+ anchors.fill: Image
+ onClicked: { Container.state = Container.state=="Edit" ? "" : "Edit" }
+ states: [
+ State {
+ when: MouseRegion.pressed == true
+ SetProperties {
+ target: Pressed
+ opacity: 1
+ }
+ }
+ ]
+ }
+
+ Text {
+ id: Label
+ font.bold: true
+ color: "white"
+ anchors.verticalCenter: Container.verticalCenter
+ x: (Container.width - width)/2
+ text: Container.label + "..."
+ }
+
+ TextEdit {
+ id: Editor
+ font.bold: true
+ color: "white"
+ highlightColor: "green"
+ width: 0
+ clip: true
+ anchors.left: Label.right
+ anchors.verticalCenter: Container.verticalCenter
+ }
+ KeyProxy {
+ id: Proxy
+ anchors.left: Container.left
+ anchors.fill: Container
+ focusable: true
+ targets: [(ReturnKey), (Editor)]
+ }
+ KeyActions {
+ id: ReturnKey
+ return: "Container.state = ''"
+ }
+}
diff --git a/demos/declarative/flickr/content/Progress.qml b/demos/declarative/flickr/content/Progress.qml
new file mode 100644
index 0000000..743c45e
--- /dev/null
+++ b/demos/declarative/flickr/content/Progress.qml
@@ -0,0 +1,33 @@
+Item {
+ id: Progress;
+
+ property var progress: 0
+
+ Rect {
+ id: Container; anchors.fill: parent
+ pen.color: "white"; pen.width: 0; radius: height/2 - 2
+ gradient: Gradient {
+ GradientStop { position: 0; color: "#66343434" }
+ GradientStop { position: 1.0; color: "#66000000" }
+ }
+ }
+
+ Rect {
+ id: Fill
+ y: 2; height: parent.height-4;
+ x: 2; width: Math.max(parent.width * progress - 4, 0);
+ opacity: width < 1 ? 0 : 1
+ gradient: Gradient {
+ GradientStop { position: 0; color: "lightsteelblue" }
+ GradientStop { position: 1.0; color: "steelblue" }
+ }
+ radius: height/2 - 2
+ }
+
+ Text {
+ text: Math.round(progress * 100) + "%"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ color: "white"; font.bold: true
+ }
+}
diff --git a/demos/declarative/flickr/content/ScrollBar.qml b/demos/declarative/flickr/content/ScrollBar.qml
new file mode 100644
index 0000000..2c4ff54
--- /dev/null
+++ b/demos/declarative/flickr/content/ScrollBar.qml
@@ -0,0 +1,38 @@
+Item {
+ id: Container
+
+ property var flickableArea
+
+ Rect {
+ radius: 5
+ color: "black"
+ opacity: 0.3
+ pen.color: "white"
+ pen.width: 2
+ x: 0
+ y: flickableArea.pageYPosition * Container.height
+ width: parent.width
+ height: flickableArea.pageHeight * Container.height
+ }
+ states: [
+ State {
+ name: "show"
+ when: flickableArea.moving
+ SetProperties {
+ target: Container
+ opacity: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "*"
+ NumericAnimation {
+ target: Container
+ properties: "opacity"
+ duration: 400
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/content/Slider.qml b/demos/declarative/flickr/content/Slider.qml
new file mode 100644
index 0000000..931dfe3
--- /dev/null
+++ b/demos/declarative/flickr/content/Slider.qml
@@ -0,0 +1,34 @@
+Item {
+ id: Slider; width: 400; height: 16
+
+ // value is read/write.
+ property real value
+ onValueChanged: { Handle.x = 2 + (value - minimum) * Slider.xMax / (maximum - minimum); }
+ property real maximum: 1
+ property real minimum: 1
+ property int xMax: Slider.width - Handle.width - 4
+
+ Rect {
+ id: Container; anchors.fill: parent
+ pen.color: "white"; pen.width: 0; radius: 8
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#66343434" }
+ GradientStop { position: 1.0; color: "#66000000" }
+ }
+ }
+
+ Rect {
+ id: Handle
+ x: Slider.width / 2 - Handle.width / 2; y: 2; width: 30; height: Slider.height-4; radius: 6
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightgray" }
+ GradientStop { position: 1.0; color: "gray" }
+ }
+
+ MouseRegion {
+ anchors.fill: parent; drag.target: parent
+ drag.axis: "x"; drag.xmin: 2; drag.xmax: Slider.xMax+2
+ onPositionChanged: { value = (maximum - minimum) * (Handle.x-2) / Slider.xMax + minimum; }
+ }
+ }
+}
diff --git a/demos/declarative/flickr/content/Star.qml b/demos/declarative/flickr/content/Star.qml
new file mode 100644
index 0000000..22fc138
--- /dev/null
+++ b/demos/declarative/flickr/content/Star.qml
@@ -0,0 +1,44 @@
+Item {
+ id: Container
+ width: 24
+ height: 24
+
+ property string rating
+ property string on
+
+ signal clicked
+
+ Image {
+ id: Image
+ source: "pics/ghns_star.png"
+ x: 6
+ y: 7
+ opacity: 0.4
+ scale: 0.5
+ }
+ MouseRegion {
+ anchors.fill: Container
+ onClicked: { Container.clicked.emit() }
+ }
+ states: [
+ State {
+ name: "on"
+ when: Container.on == true
+ SetProperties {
+ target: Image
+ opacity: 1
+ scale: 1
+ x: 1
+ y: 0
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "opacity,scale,x,y"
+ easing: "easeOutBounce"
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/content/pics/background.png b/demos/declarative/flickr/content/pics/background.png
new file mode 100644
index 0000000..5b37072
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/background.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/button-pressed.png b/demos/declarative/flickr/content/pics/button-pressed.png
new file mode 100644
index 0000000..e434d32
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/button-pressed.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/button-pressed.sci b/demos/declarative/flickr/content/pics/button-pressed.sci
new file mode 100644
index 0000000..d3b16e2
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/button-pressed.sci
@@ -0,0 +1,5 @@
+gridLeft: 8
+gridTop: 4
+gridBottom: 4
+gridRight: 8
+imageFile: button.png
diff --git a/demos/declarative/flickr/content/pics/button.png b/demos/declarative/flickr/content/pics/button.png
new file mode 100644
index 0000000..56a63ce
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/button.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/button.sci b/demos/declarative/flickr/content/pics/button.sci
new file mode 100644
index 0000000..d3b16e2
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/button.sci
@@ -0,0 +1,5 @@
+gridLeft: 8
+gridTop: 4
+gridBottom: 4
+gridRight: 8
+imageFile: button.png
diff --git a/demos/declarative/flickr/content/pics/ghns_star.png b/demos/declarative/flickr/content/pics/ghns_star.png
new file mode 100644
index 0000000..4ad43cc
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/ghns_star.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/loading.png b/demos/declarative/flickr/content/pics/loading.png
new file mode 100644
index 0000000..47a1589
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/loading.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/reflection.png b/demos/declarative/flickr/content/pics/reflection.png
new file mode 100644
index 0000000..c143a48
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/reflection.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/shadow-bottom.png b/demos/declarative/flickr/content/pics/shadow-bottom.png
new file mode 100644
index 0000000..523f6e7
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/shadow-bottom.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/shadow-corner.png b/demos/declarative/flickr/content/pics/shadow-corner.png
new file mode 100644
index 0000000..ef8c856
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/shadow-corner.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/shadow-right-screen.png b/demos/declarative/flickr/content/pics/shadow-right-screen.png
new file mode 100644
index 0000000..9856c4f
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/shadow-right-screen.png
Binary files differ
diff --git a/demos/declarative/flickr/content/pics/shadow-right.png b/demos/declarative/flickr/content/pics/shadow-right.png
new file mode 100644
index 0000000..f534a35
--- /dev/null
+++ b/demos/declarative/flickr/content/pics/shadow-right.png
Binary files differ
diff --git a/demos/declarative/flickr/flickr.qml b/demos/declarative/flickr/flickr.qml
new file mode 100644
index 0000000..da77d93
--- /dev/null
+++ b/demos/declarative/flickr/flickr.qml
@@ -0,0 +1,208 @@
+import "content"
+
+Item {
+ id: MainWindow; width: 800; height: 450
+
+ property bool showPathView : false
+
+ resources: [
+ XmlListModel {
+ id: FeedModel
+ property string tags : TagsEdit.text
+ source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+ query: "doc($src)/rss/channel/item"
+ namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+ Role { name: "title"; query: "title/string()" }
+ Role { name: "imagePath"; query: "media:thumbnail/@url/string()" }
+ Role { name: "url"; query: "media:content/@url/string()" }
+ Role { name: "description"; query: "description/string()"; isCData: true }
+ Role { name: "tags"; query: "media:category/string()" }
+ Role { name: "photoWidth"; query: "media:content/@width/string()" }
+ Role { name: "photoHeight"; query: "media:content/@height/string()" }
+ Role { name: "photoType"; query: "media:content/@type/string()" }
+ Role { name: "photoAuthor"; query: "author/string()" }
+ Role { name: "photoDate"; query: "pubDate/string()" }
+ },
+
+ Component {
+ id: PhotoDelegate
+ Item {
+ id: Wrapper; width: 85; height: 85
+ scale: Wrapper.PathView.scale; z: Wrapper.PathView.z
+
+ transform: [
+ Rotation3D { id: Rotation; axis.startX: 30; axis.endX: 30; axis.endY: 60; angle: Wrapper.PathView.angle }
+ ]
+
+ Connection {
+ sender: ImageDetails; signal: "closed()"
+ script: {
+ if (Wrapper.state == 'Details') {
+ Wrapper.state = '';
+ ImageDetails.photoUrl = "";
+ }
+ }
+ }
+
+ Script {
+ function photoClicked() {
+ ImageDetails.photoTitle = title;
+ ImageDetails.photoDescription = description;
+ ImageDetails.photoTags = tags;
+ ImageDetails.photoWidth = photoWidth;
+ ImageDetails.photoHeight = photoHeight;
+ ImageDetails.photoType = photoType;
+ ImageDetails.photoAuthor = photoAuthor;
+ ImageDetails.photoDate = photoDate;
+ ImageDetails.photoUrl = url;
+ ImageDetails.rating = 0;
+ Wrapper.state = "Details";
+ }
+ }
+
+ Rect {
+ id: WhiteRect; anchors.fill: parent; color: "white"; radius: 5
+
+ Loading { x: 26; y: 26; visible: Thumb.status }
+ Image { id: Thumb; source: imagePath; x: 5; y: 5 }
+
+ Item {
+ id: Shadows
+ Image { source: "content/pics/shadow-right.png"; x: WhiteRect.width; height: WhiteRect.height }
+ Image { source: "content/pics/shadow-bottom.png"; y: WhiteRect.height; width: WhiteRect.width }
+ Image { id: Corner; source: "content/pics/shadow-corner.png"; x: WhiteRect.width; y: WhiteRect.height }
+ }
+ }
+
+ MouseRegion { anchors.fill: Wrapper; onClicked: { photoClicked() } }
+
+ states: [
+ State {
+ name: "Details"
+ SetProperties { target: ImageDetails; z: 2 }
+ ParentChange { target: Wrapper; parent: ImageDetails.frontContainer }
+ SetProperties { target: Wrapper; x: 45; y: 35; scale: 1; z: 1000 }
+ SetProperties { target: Rotation; angle: 0 }
+ SetProperties { target: Shadows; opacity: 0 }
+ SetProperties { target: ImageDetails; y: 20 }
+ SetProperties { target: PhotoGridView; y: "-480" }
+ SetProperties { target: PhotoPathView; y: "-480" }
+ SetProperties { target: ViewModeButton; opacity: 0 }
+ SetProperties { target: TagsEdit; opacity: 0 }
+ SetProperties { target: FetchButton; opacity: 0 }
+ SetProperties { target: CategoryText; y: "-50" }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ fromState: "*"; toState: "Details"
+ ParentChangeAction { }
+ NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" }
+ },
+ Transition {
+ fromState: "Details"; toState: "*"
+ SequentialAnimation {
+ ParentChangeAction { }
+ NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" }
+ SetPropertyAction { filter: Wrapper; properties: "z" }
+ }
+ }
+ ]
+
+ }
+ }
+ ]
+
+ Item {
+ id: Background
+
+ anchors.fill: parent
+
+ Image { source: "content/pics/background.png"; opaque: true; anchors.fill: parent }
+
+ Loading { anchors.centeredIn: parent; visible: FeedModel.status != 0 }
+
+ GridView {
+ id: PhotoGridView; model: FeedModel; delegate: PhotoDelegate; cacheBuffer: 100
+ cellWidth: 105; cellHeight: 105; x:32; y: 80; width: 800; height: 330; z: 1
+ }
+
+ PathView {
+ id: PhotoPathView; model: FeedModel; delegate: PhotoDelegate
+ y: -380; width: 800; height: 330; pathItemCount: 10; z: 1
+ path: Path {
+ startX: -50; startY: 40;
+
+ PathAttribute { name: "scale"; value: 1 }
+ PathAttribute { name: "angle"; value: -45 }
+
+ PathCubic {
+ x: 400; y: 220
+ control1X: 140; control1Y: 40
+ control2X: 210; control2Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 1.2 }
+ PathAttribute { name: "z"; value: 1 }
+ PathAttribute { name: "angle"; value: 0 }
+
+ PathCubic {
+ x: 850; y: 40
+ control2X: 660; control2Y: 40
+ control1X: 590; control1Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 1 }
+ PathAttribute { name: "angle"; value: 45 }
+ }
+
+ }
+
+ ImageDetails { id: ImageDetails; width: 750; x: 25; y: 500; height: 410 }
+
+ MediaButton {
+ id: ViewModeButton; x: 680; y: 410; text: "View Mode"
+ onClicked: { if (MainWindow.showPathView == true) MainWindow.showPathView = false; else MainWindow.showPathView = true }
+ }
+
+ MediaButton {
+ id: FetchButton
+ text: "Update"
+ anchors.right: ViewModeButton.left; anchors.rightMargin: 5
+ anchors.top: ViewModeButton.top
+ onClicked: { FeedModel.reload(); }
+ }
+
+ MediaLineEdit {
+ id: TagsEdit;
+ label: "Tags"
+ anchors.right: FetchButton.left; anchors.rightMargin: 5
+ anchors.top: ViewModeButton.top
+ }
+
+ states: [
+ State {
+ name: "PathView"
+ when: MainWindow.showPathView == true
+ SetProperties { target: PhotoPathView; y: 80 }
+ SetProperties { target: PhotoGridView; y: -380 }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ fromState: "*"; toState: "*"
+ NumericAnimation { properties: "y"; duration: 1000; easing: "easeOutBounce(amplitude:0.5)" }
+ }
+ ]
+ }
+
+ Text {
+ id: CategoryText; anchors.horizontalCenter: parent.horizontalCenter; y: 15;
+ text: "Flickr - " +
+ (FeedModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + FeedModel.tags)
+ font.size: 20; font.bold: true; color: "white"; style: "Raised"; styleColor: "black"
+ }
+}
diff --git a/demos/declarative/flickr/flickr2.qml b/demos/declarative/flickr/flickr2.qml
new file mode 100644
index 0000000..52f8675
--- /dev/null
+++ b/demos/declarative/flickr/flickr2.qml
@@ -0,0 +1,263 @@
+import "content"
+
+Item {
+ id: MainWindow; width: 800; height: 450
+
+ property bool showPathView : false
+
+ VisualModel {
+ id: MyVisualModel
+ model:
+ XmlListModel {
+ id: FeedModel
+ property string tags : TagsEdit.text
+ source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+ query: "doc($src)/rss/channel/item"
+ namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+ Role { name: "title"; query: "title/string()" }
+ Role { name: "imagePath"; query: "media:thumbnail/@url/string()" }
+ Role { name: "url"; query: "media:content/@url/string()" }
+ Role { name: "description"; query: "description/string()"; isCData: true }
+ Role { name: "tags"; query: "media:category/string()" }
+ Role { name: "photoWidth"; query: "media:content/@width/string()" }
+ Role { name: "photoHeight"; query: "media:content/@height/string()" }
+ Role { name: "photoType"; query: "media:content/@type/string()" }
+ Role { name: "photoAuthor"; query: "author/string()" }
+ Role { name: "photoDate"; query: "pubDate/string()" }
+ }
+
+ delegate: Package {
+ Item {
+ id: Wrapper; width: 85; height: 85; scale: {1.0}
+ z: PathViewPackage.PathView.z
+ property real angle: 0 * 0
+
+ transform: [
+ Rotation3D {
+ id: Rotation; axis.startX: 30; axis.endX: 30; axis.endY: 60
+ angle: Wrapper.angle
+ }
+ ]
+
+ Connection {
+ sender: Background.imageDetails; signal: "closed()"
+ script: { if (Wrapper.state == 'Details') Wrapper.state = '' }
+ }
+
+ Script {
+ function photoClicked() {
+ Background.imageDetails.photoTitle = title;
+ Background.imageDetails.flickableArea.yPosition = 0;
+ Background.imageDetails.photoDescription = description;
+ Background.imageDetails.photoTags = tags;
+ Background.imageDetails.photoWidth = photoWidth;
+ Background.imageDetails.photoHeight = photoHeight;
+ Background.imageDetails.photoType = photoType;
+ Background.imageDetails.photoAuthor = photoAuthor;
+ Background.imageDetails.photoDate = photoDate;
+ Background.imageDetails.photoUrl = url;
+ Background.imageDetails.rating = 0;
+ Wrapper.state = "Details";
+ }
+ }
+
+ Rect {
+ id: WhiteRect; anchors.fill: parent; color: "white"; radius: 5
+
+ Loading { x: 26; y: 26; visible: Thumb.status }
+ Image { id: Thumb; source: imagePath; x: 5; y: 5 }
+
+ Item {
+ id: Shadows
+ Image { source: "content/pics/shadow-right.png"; x: WhiteRect.width; height: WhiteRect.height }
+ Image { source: "content/pics/shadow-bottom.png"; y: WhiteRect.height; width: WhiteRect.width }
+ Image { id: Corner; source: "content/pics/shadow-corner.png"; x: WhiteRect.width; y: WhiteRect.height }
+ }
+ }
+
+ MouseRegion { anchors.fill: Wrapper; onClicked: { photoClicked() } }
+
+ states: [
+ State {
+ name: "Details"
+ SetProperties { target: Background.imageDetails; z: 2 }
+ ParentChange { target: Wrapper; parent: Background.imageDetails.frontContainer }
+ SetProperties { target: Wrapper; x: 45; y: 35; scale: 1; z: 1000 }
+ SetProperties { target: Rotation; angle: 0 }
+ SetProperties { target: Shadows; opacity: 0 }
+ SetProperties { target: Background.imageDetails; y: 20 }
+ SetProperties { target: PhotoGridView; y: "-480" }
+ SetProperties { target: PhotoPathView; y: "-480" }
+ SetProperties { target: ViewModeButton; opacity: 0 }
+ SetProperties { target: TagsEdit; opacity: 0 }
+ SetProperties { target: FetchButton; opacity: 0 }
+ SetProperties { target: CategoryText; y: "-50" }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ fromState: "*"; toState: "Details"
+ ParentChangeAction { }
+ NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" }
+ },
+ Transition {
+ fromState: "Details"; toState: "*"
+ SequentialAnimation {
+ ParentChangeAction { }
+ NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" }
+ SetPropertyAction { filter: Wrapper; properties: "z" }
+ }
+ }
+ ]
+ }
+
+ Item {
+ Package.name: "pathView"
+ id: PathViewPackage; width: 85; height: 85
+ }
+
+ Item {
+ Package.name: "gridView"
+ id: GridViewPackage; width: 85; height: 85
+ }
+
+ Item {
+ id: MyItem
+ state: MainWindow.showPathView ? "pathView" : "gridView"
+ states: [
+ State {
+ name: "gridView"
+ SetProperty { target: Wrapper; property: "moveToParent"; value: GridViewPackage }
+ },
+ State {
+ name: "pathView"
+ SetProperty { target: Wrapper; property: "scale"; value: PathViewPackage.PathView.scale }
+ SetProperty { target: Wrapper; property: "scale"; binding: "PathViewPackage.PathView.scale" }
+ SetProperty { target: Wrapper; property: "angle"; value: PathViewPackage.PathView.angle }
+ SetProperty { target: Wrapper; property: "angle"; binding: "PathViewPackage.PathView.angle" }
+ SetProperty { target: Wrapper; property: "moveToParent"; value: PathViewPackage }
+ }
+ ]
+ transitions: [
+ Transition {
+ toState: "pathView"
+ SequentialAnimation {
+ SetPropertyAction { target: Wrapper; property: "moveToParent" }
+ ParallelAnimation {
+ NumericAnimation {
+ target: Wrapper
+ properties: "x,y"
+ to: 0
+ easing: "easeOutQuad"
+ duration: 350
+ }
+ NumericAnimation { target: Wrapper; properties: "scale,angle"; duration: 350 }
+ }
+ }
+ },
+ Transition {
+ toState: "gridView"
+ SequentialAnimation {
+ PauseAnimation { duration: Math.floor(index/7)*100 }
+ SetPropertyAction { target: Wrapper; property: "moveToParent" }
+ ParallelAnimation {
+ NumericAnimation {
+ target: Wrapper
+ properties: "x,y"
+ to: 0
+ easing: "easeOutQuad"
+ duration: 250
+ }
+ NumericAnimation { target: Wrapper; properties: "scale,angle"; duration: 250 }
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+
+
+ Item {
+ id: Background
+ property var imageDetails: ImageDetails
+
+ Image { source: "content/pics/background.png"; opaque: true }
+
+ GridView {
+ id: PhotoGridView; model: MyVisualModel.parts.gridView
+ cellWidth: 105; cellHeight: 105; x:32; y: 80; width: 800; height: 330; z: 1
+ cacheBuffer: 100
+ }
+
+ PathView {
+ id: PhotoPathView; model: MyVisualModel.parts.pathView
+ y: 80; width: 800; height: 330; z: 1
+ pathItemCount: 10; snapPosition: 0.001
+ path: Path {
+ startX: -150; startY: 40;
+
+ PathAttribute { name: "scale"; value: 0.9 }
+ PathAttribute { name: "angle"; value: -45 }
+ PathPercent { value: 0 }
+ PathLine { x: -50; y: 40 }
+
+ PathPercent { value: 0.001 }
+
+ PathCubic {
+ x: 400; y: 220
+ control1X: 140; control1Y: 40
+ control2X: 210; control2Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 1.2 }
+ PathAttribute { name: "z"; value: 1 }
+ PathAttribute { name: "angle"; value: 0 }
+
+ PathCubic {
+ x: 850; y: 40
+ control2X: 660; control2Y: 40
+ control1X: 590; control1Y: 220
+ }
+
+ PathPercent { value: 0.999 }
+ PathLine { x: 950; y: 40 }
+ PathPercent { value: 1.0 }
+ PathAttribute { name: "scale"; value: 0.9 }
+ PathAttribute { name: "angle"; value: 45 }
+ }
+ }
+
+ ImageDetails { id: ImageDetails; width: 750; x: 25; y: 500; height: 410 }
+
+ MediaButton {
+ id: ViewModeButton; x: 680; y: 410; text: "View Mode"
+ onClicked: { if (MainWindow.showPathView == true) MainWindow.showPathView = false; else MainWindow.showPathView = true }
+ }
+
+ MediaButton {
+ id: FetchButton
+ text: "Update"
+ anchors.right: ViewModeButton.left; anchors.rightMargin: 5
+ anchors.top: ViewModeButton.top
+ onClicked: { FeedModel.reload(); }
+ }
+
+ MediaLineEdit {
+ id: TagsEdit;
+ label: "Tags"
+ anchors.right: FetchButton.left; anchors.rightMargin: 5
+ anchors.top: ViewModeButton.top
+ }
+
+ }
+
+ Text {
+ id: CategoryText; anchors.horizontalCenter: parent.horizontalCenter; y: 15;
+ text: "Flickr - " +
+ (FeedModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + FeedModel.tags)
+ font.size: 16; font.bold: true; color: "white"; style: "Raised"; styleColor: "black"
+ }
+}
diff --git a/demos/declarative/webbrowser/README b/demos/declarative/webbrowser/README
new file mode 100644
index 0000000..7bfd41f
--- /dev/null
+++ b/demos/declarative/webbrowser/README
@@ -0,0 +1,6 @@
+For good performance, be sure to use disk cache for remote content:
+
+ duiviewer -cache webbrowser.qml
+
+Otherwise everything always re-loads over the network.
+
diff --git a/demos/declarative/webbrowser/content/RectSoftShadow.qml b/demos/declarative/webbrowser/content/RectSoftShadow.qml
new file mode 100644
index 0000000..1734433
--- /dev/null
+++ b/demos/declarative/webbrowser/content/RectSoftShadow.qml
@@ -0,0 +1,30 @@
+Item {
+ Image {
+ source: "pics/softshadow-left.sci"
+ x: -16
+ y: -16
+ width: 16
+ height: parent.height+32
+ }
+ Image {
+ source: "pics/softshadow-right.sci"
+ x: parent.width
+ y: -16
+ width: 16
+ height: parent.height+32
+ }
+ Image {
+ source: "pics/softshadow-top.png"
+ x: 0
+ y: -16
+ width: parent.width
+ height: 16
+ }
+ Image {
+ source: "pics/softshadow-bottom.png"
+ x: 0
+ y: parent.height
+ width: WebView.width*WebView.scale
+ height: 16
+ }
+}
diff --git a/demos/declarative/webbrowser/content/pics/addressbar-filled.png b/demos/declarative/webbrowser/content/pics/addressbar-filled.png
new file mode 100644
index 0000000..d8452ec
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar-filled.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/addressbar-filled.sci b/demos/declarative/webbrowser/content/pics/addressbar-filled.sci
new file mode 100644
index 0000000..464dbf5
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar-filled.sci
@@ -0,0 +1,6 @@
+gridLeft: 7
+gridTop: 7
+gridBottom: 7
+gridRight: 7
+imageFile: addressbar-filled.png
+
diff --git a/demos/declarative/webbrowser/content/pics/addressbar.png b/demos/declarative/webbrowser/content/pics/addressbar.png
new file mode 100644
index 0000000..3278f58
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/addressbar.sci b/demos/declarative/webbrowser/content/pics/addressbar.sci
new file mode 100644
index 0000000..23a2a19
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar.sci
@@ -0,0 +1,6 @@
+gridLeft: 7
+gridTop: 7
+gridBottom: 7
+gridRight: 7
+imageFile: addressbar.png
+
diff --git a/demos/declarative/webbrowser/content/pics/back-disabled.png b/demos/declarative/webbrowser/content/pics/back-disabled.png
new file mode 100644
index 0000000..91b9e76
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/back-disabled.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/back.png b/demos/declarative/webbrowser/content/pics/back.png
new file mode 100644
index 0000000..9988dd3
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/back.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/footer.png b/demos/declarative/webbrowser/content/pics/footer.png
new file mode 100644
index 0000000..8391a93
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/footer.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/footer.sci b/demos/declarative/webbrowser/content/pics/footer.sci
new file mode 100644
index 0000000..be1d086
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/footer.sci
@@ -0,0 +1,6 @@
+gridLeft: 5
+gridTop: 0
+gridBottom: 0
+gridRight: 5
+imageFile: footer.png
+
diff --git a/demos/declarative/webbrowser/content/pics/forward-disabled.png b/demos/declarative/webbrowser/content/pics/forward-disabled.png
new file mode 100644
index 0000000..cb87f4f
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/forward-disabled.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/forward.png b/demos/declarative/webbrowser/content/pics/forward.png
new file mode 100644
index 0000000..83870ee
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/forward.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/header.png b/demos/declarative/webbrowser/content/pics/header.png
new file mode 100644
index 0000000..26588c3
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/header.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/reload.png b/demos/declarative/webbrowser/content/pics/reload.png
new file mode 100644
index 0000000..45b5535
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/reload.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-bottom.png b/demos/declarative/webbrowser/content/pics/softshadow-bottom.png
new file mode 100644
index 0000000..85b0b44
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-bottom.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-left.png b/demos/declarative/webbrowser/content/pics/softshadow-left.png
new file mode 100644
index 0000000..02926d1
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-left.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-left.sci b/demos/declarative/webbrowser/content/pics/softshadow-left.sci
new file mode 100644
index 0000000..82e38f8
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-left.sci
@@ -0,0 +1,5 @@
+gridLeft: 0
+gridTop: 16
+gridBottom: 16
+gridRight: 0
+imageFile: softshadow-left.png
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-right.png b/demos/declarative/webbrowser/content/pics/softshadow-right.png
new file mode 100644
index 0000000..e459f4f
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-right.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-right.sci b/demos/declarative/webbrowser/content/pics/softshadow-right.sci
new file mode 100644
index 0000000..e9494ed
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-right.sci
@@ -0,0 +1,5 @@
+gridLeft: 0
+gridTop: 16
+gridBottom: 16
+gridRight: 0
+imageFile: softshadow-right.png
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-top.png b/demos/declarative/webbrowser/content/pics/softshadow-top.png
new file mode 100644
index 0000000..9a9e232
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-top.png
Binary files differ
diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml
new file mode 100644
index 0000000..a38d032
--- /dev/null
+++ b/demos/declarative/webbrowser/webbrowser.qml
@@ -0,0 +1,429 @@
+import "content"
+
+Item {
+ id: WebBrowser
+
+ property var url : "http://www.qtsoftware.com"
+
+ width: 640
+ height: 480
+ state: "Normal"
+
+ Script {
+ function zoomOut() {
+ WebBrowser.state = "ZoomedOut";
+ }
+ function toggleZoom() {
+ if(WebBrowser.state == "ZoomedOut") {
+ Flick.centerX = WebView.mouseX;
+ Flick.centerY = WebView.mouseY;
+ WebBrowser.state = "Normal";
+ } else {
+ zoomOut();
+ }
+ }
+ }
+
+ Item {
+ id: WebPanel
+ anchors.fill: parent
+ clip: true
+ Rect {
+ color: "#555555"
+ anchors.fill: parent
+ }
+ Image {
+ source: "content/pics/softshadow-bottom.png"
+ width: WebPanel.width
+ height: 16
+ }
+ Image {
+ source: "content/pics/softshadow-top.png"
+ width: WebPanel.width
+ height: 16
+ anchors.bottom: Footer.top
+ }
+ RectSoftShadow {
+ x: -Flick.xPosition
+ y: -Flick.yPosition
+ width: WebView.width*WebView.scale
+ height: Flick.y+WebView.height*WebView.scale
+ }
+ Item {
+ id: HeaderSpace
+ width: parent.width
+ height: 60
+ z: 1
+
+ Image {
+ id: Header
+ source: "content/pics/header.png"
+ width: parent.width
+ height: 64
+ state: "Normal"
+ x: Flick.xPosition < 0 ? -Flick.xPosition : Flick.xPosition > Flick.viewportWidth-Flick.width
+ ? -Flick.xPosition+Flick.viewportWidth-Flick.width : 0
+ y: Flick.yPosition < 0 ? -Flick.yPosition : progressOff*
+ (Flick.yPosition>height?-height:-Flick.yPosition)
+ Text {
+ id: HeaderText
+
+ text: WebView.title!='' || WebView.progress == 1.0 ? WebView.title : 'Loading...'
+ elide: "ElideRight"
+
+ color: "white"
+ styleColor: "black"
+ style: "Raised"
+
+ font.family: "Helvetica"
+ font.size: 10
+ font.bold: true
+
+ anchors.left: Header.left
+ anchors.right: Header.right
+ anchors.leftMargin: 4
+ anchors.rightMargin: 4
+ anchors.top: Header.top
+ anchors.topMargin: 4
+ hAlign: "AlignHCenter"
+ }
+ Item {
+ width: parent.width
+ anchors.top: HeaderText.bottom
+ anchors.topMargin: 2
+ anchors.bottom: parent.bottom
+
+ Item {
+ id: UrlBox
+ height: 31
+ anchors.left: parent.left
+ anchors.leftMargin: 12
+ anchors.right: parent.right
+ anchors.rightMargin: 12
+ anchors.top: parent.top
+ clip: true
+ Image {
+ source: "content/pics/addressbar.sci"
+ anchors.fill: UrlBox
+ }
+ Image {
+ id: UrlBoxhl
+ source: "content/pics/addressbar-filled.sci"
+ width: parent.width*WebView.progress
+ height: parent.height
+ opacity: 1-Header.progressOff
+ clip: true
+ }
+
+ /*
+ KeyProxy {
+ id: proxy
+ anchors.left: UrlBox.left
+ anchors.fill: UrlBox
+ focusable: true
+ targets: [keyActions,EditUrl]
+ }
+ KeyActions {
+ id: keyActions
+ return: "WebBrowser.url = EditUrl.text; proxy.focus=false;"
+ }
+ */
+ TextEdit {
+ id: EditUrl
+
+ text: WebView.url == '' ? ' ' : WebView.url
+ wrap: false
+ font.size: 11
+ color: "#555555"
+ focusOnPress: true
+
+ anchors.left: UrlBox.left
+ anchors.right: UrlBox.right
+ anchors.leftMargin: 6
+ anchors.verticalCenter: UrlBox.verticalCenter
+ anchors.verticalCenterOffset: 1
+ }
+ }
+ }
+
+ property real progressOff : 1
+ states: [
+ State {
+ name: "Normal"
+ when: WebView.progress == 1.0
+ SetProperty {
+ target: Header
+ property: "progressOff"
+ value: 1
+ }
+ },
+ State {
+ name: "ProgressShown"
+ when: WebView.progress < 1.0
+ SetProperty {
+ target: Header
+ property: "progressOff"
+ value: 0
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ target: Header
+ properties: "progressOff"
+ easing: "easeInOutQuad"
+ duration: 300
+ }
+ }
+ ]
+ }
+ }
+ Flickable {
+ id: Flick
+ width: parent.width
+ viewportWidth: Math.max(parent.width,WebView.width*WebView.scale)
+ viewportHeight: Math.max(parent.height,WebView.height*WebView.scale)
+ anchors.top: HeaderSpace.bottom
+ anchors.bottom: Footer.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ property real centerX : 0
+ property real centerY : 0
+
+ WebView {
+ id: WebView
+ cacheSize: 4000000
+
+ url: WebBrowser.url
+ smooth: true
+ focusable: true
+ focus: true
+
+ idealWidth: Flick.width
+ idealHeight: Flick.height/scale
+ scale: (width > 0) ? Flick.width/width*zoomedOut+(1-zoomedOut) : 1
+
+ onUrlChanged: { Flick.xPosition=0; Flick.yPosition=0; zoomOut() }
+ onDoubleClick: { toggleZoom() }
+
+ property real zoomedOut : 1
+ }
+ Rect {
+ id: WebViewTint
+ color: "black"
+ opacity: 0
+ anchors.fill: WebView
+ MouseRegion {
+ anchors.fill: WebViewTint
+ onClicked: { proxy.focus=false }
+ }
+ }
+ }
+ Image {
+ id: Footer
+ source: "content/pics/footer.sci"
+ width: parent.width
+ height: 43
+ anchors.bottom: parent.bottom
+ Rect {
+ y: -1
+ width: parent.width
+ height: 1
+ color: "#555555"
+ }
+ Item {
+ id: backbutton
+ width: back_e.width
+ height: back_e.height
+ anchors.right: reload.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ Image {
+ id: back_e
+ source: "content/pics/back.png"
+ anchors.fill: parent
+ }
+ Image {
+ id: back_d
+ source: "content/pics/back-disabled.png"
+ anchors.fill: parent
+ }
+ states: [
+ State {
+ name: "Enabled"
+ when: WebView.back.enabled==true
+ SetProperty {
+ target: back_e
+ property: "opacity"
+ value: 1
+ }
+ SetProperty {
+ target: back_d
+ property: "opacity"
+ value: 0
+ }
+ },
+ State {
+ name: "Disabled"
+ when: WebView.back.enabled==false
+ SetProperty {
+ target: back_e
+ property: "opacity"
+ value: 0
+ }
+ SetProperty {
+ target: back_d
+ property: "opacity"
+ value: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "opacity"
+ easing: "easeInOutQuad"
+ duration: 300
+ }
+ }
+ ]
+ MouseRegion {
+ anchors.fill: back_e
+ onClicked: { if (WebView.back.enabled) WebView.back.trigger() }
+ }
+ }
+ Image {
+ id: reload
+ source: "content/pics/reload.png"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ MouseRegion {
+ anchors.fill: reload
+ onClicked: { WebView.reload.trigger() }
+ }
+ Item {
+ id: forwardbutton
+ width: forward_e.width
+ height: forward_e.height
+ anchors.left: reload.right
+ anchors.leftMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ Image {
+ id: forward_e
+ source: "content/pics/forward.png"
+ anchors.fill: parent
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ Image {
+ id: forward_d
+ source: "content/pics/forward-disabled.png"
+ anchors.fill: parent
+ }
+ states: [
+ State {
+ name: "Enabled"
+ when: WebView.forward.enabled==true
+ SetProperty {
+ target: forward_e
+ property: "opacity"
+ value: 1
+ }
+ SetProperty {
+ target: forward_d
+ property: "opacity"
+ value: 0
+ }
+ },
+ State {
+ name: "Disabled"
+ when: WebView.forward.enabled==false
+ SetProperty {
+ target: forward_e
+ property: "opacity"
+ value: 0
+ }
+ SetProperty {
+ target: forward_d
+ property: "opacity"
+ value: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "opacity"
+ easing: "easeInOutQuad"
+ duration: 320
+ }
+ }
+ ]
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { if (WebView.forward.enabled) WebView.forward.trigger() }
+ }
+ }
+ }
+ }
+ states: [
+ State {
+ name: "Normal"
+ SetProperty {
+ target: WebView
+ property: "zoomedOut"
+ value: 0
+ }
+ SetProperty {
+ target: Flick
+ property: "xPosition"
+ value: Math.min(WebView.width-Flick.width,Math.max(0,Flick.centerX-Flick.width/2))
+ }
+ SetProperty {
+ target: Flick
+ property: "yPosition"
+ value: Math.min(WebView.height-Flick.height,Math.max(0,Flick.centerY-Flick.height/2))
+ }
+ },
+ State {
+ name: "ZoomedOut"
+ SetProperty {
+ target: WebView
+ property: "zoomedOut"
+ value: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ SequentialAnimation {
+ SetPropertyAction {
+ target: WebView
+ property: "smooth"
+ value: false
+ }
+ ParallelAnimation {
+ NumericAnimation {
+ target: WebView
+ properties: "zoomedOut"
+ easing: "easeInOutQuad"
+ duration: 200
+ }
+ NumericAnimation {
+ target: Flick
+ properties: "xPosition,yPosition"
+ easing: "easeInOutQuad"
+ duration: 200
+ }
+ }
+ SetPropertyAction {
+ target: WebView
+ property: "smooth"
+ value: true
+ }
+ }
+ }
+ ]
+}
diff --git a/doc/doc.pri b/doc/doc.pri
index a4c77fe..367ef29 100644
--- a/doc/doc.pri
+++ b/doc/doc.pri
@@ -32,13 +32,14 @@ macx {
ADP_DOCS_QDOCCONF_FILE = qt-build-docs.qdocconf
}
QT_DOCUMENTATION = ($$QDOC qt-api-only.qdocconf assistant.qdocconf designer.qdocconf \
- linguist.qdocconf qmake.qdocconf) && \
+ linguist.qdocconf qmake.qdocconf qml.qdocconf) && \
(cd $$QT_BUILD_TREE && \
$$GENERATOR doc-build/html-qt/qt.qhp -o doc/qch/qt.qch && \
$$GENERATOR doc-build/html-assistant/assistant.qhp -o doc/qch/assistant.qch && \
$$GENERATOR doc-build/html-designer/designer.qhp -o doc/qch/designer.qch && \
$$GENERATOR doc-build/html-linguist/linguist.qhp -o doc/qch/linguist.qch && \
- $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch \
+ $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch && \
+ $$GENERATOR doc-build/html-qml/qml.qhp -o doc/qch/qml.qch \
)
win32-g++:isEmpty(QMAKE_SH) {
diff --git a/doc/src/animation.qdoc b/doc/src/animation.qdoc
index b4e603c..5675185 100644
--- a/doc/src/animation.qdoc
+++ b/doc/src/animation.qdoc
@@ -43,7 +43,7 @@
\page animation-overview.html
\title The Animation Framework
\ingroup architecture
- \ingroup animation
+ \ingroup group_animation
\brief An overview of the Animation Framework
\keyword Animation
diff --git a/doc/src/declarative/anchor-layout.qdoc b/doc/src/declarative/anchor-layout.qdoc
new file mode 100644
index 0000000..9ff902ee
--- /dev/null
+++ b/doc/src/declarative/anchor-layout.qdoc
@@ -0,0 +1,68 @@
+/*!
+\page anchor-layout.html
+\target anchor-layout
+\title Anchor-based Layout
+
+In additional to the more traditional Fx layouts GridLayout, HorizontalLayout, and VerticalLayout, QML also provides a way to layout items using the concept of anchors. Each visual Fx item can be thought of as having a set of 6 invisible "anchor lines": \e left, \e horizontalCenter, \e right, \e top, \e verticalCenter, and \e bottom.
+
+\image edges_qml.png
+
+The Fx anchoring system allows you to define relationships between the anchor lines of different items. For example, you can write:
+
+\code
+Rect { id: rect1; ... }
+Rect { id: rect2; anchors.left: rect1.right; ... }
+\endcode
+
+In this case, the left edge of \e rect2 is bound to the right edge of rect1, producing the following:
+
+\image edge1.png
+
+The anchoring system also allows you to specify margins and offsets. Margins specify the amount of empty space to leave to the outside of an item, while offsets allow you to manipulate positioning using the center anchor lines. Note that margins specified using the anchor layout system only have meaning for anchors; they won't have any effect when using other layouts or absolute positioning.
+
+\image margins_qml.png
+
+The following example specifies a left margin:
+
+\code
+Rect { id: rect1; ... }
+Rect { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }
+\endcode
+
+In this case, a margin of 5 pixels is reserved to the left of \e rect2, producing the following:
+
+\image edge2.png
+
+You can specify multiple anchors. For example:
+
+\code
+Rect { id: rect1; ... }
+Rect { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... }
+\endcode
+
+\image edge3.png
+
+By specifying multiple horizontal or vertical anchors you can control the size of an item. For example:
+
+\code
+Rect { id: rect1; x: 0; ... }
+Rect { id: rect2; anchors.left: rect1.right; anchors.right: rect3.left; ... }
+Rect { id: rect3; x: 150; ... }
+\endcode
+
+\image edge4.png
+
+\section1 Limitations
+
+For performance reasons, you can only anchor an item to its siblings and direct parent. For example, the following anchor would be considered invalid and would produce a warning:
+
+\code
+Item { id: group1 }
+ Rect { id: rect1; ... }
+}
+Item id: group2">
+ Rect { id: rect2; anchors.left: rect1.right; ... } // invalid anchor!
+}
+\endcode
+
+*/
diff --git a/doc/src/declarative/animation.qdoc b/doc/src/declarative/animation.qdoc
new file mode 100644
index 0000000..f17f5c9
--- /dev/null
+++ b/doc/src/declarative/animation.qdoc
@@ -0,0 +1,169 @@
+/*!
+\page qmlanimation.html
+\target qmlanimation
+\title QML Animation
+
+QML supports three different forms of animation - basic property animation,
+states and transitions and property behaviors.
+
+\section1 Property Animation
+
+Animation in QML is done by animating properties of objects.
+
+Any property of a recognizable type can be animated. Currently those types include:
+\list
+\o qreal
+\o int
+\o Most of QVariant's built-in types
+\endlist
+
+Animations can also involve numerous properties on numerous objects.
+
+Other Features:
+\list
+\o Support for a large set of parameterized easing curves. (based on the Penner easing equations)
+\o Animation synchronization
+\endlist
+
+The simplest form of animation is using \l NumericAnimation
+
+The following example creates a bouncing effect:
+\code
+Rect {
+ id: rect
+ width: 120; height: 200; color: "white"
+ Image {
+ id: img
+ source: "qt-logo.png"
+ x: 60-img.width/2
+ y: 0
+ y: SequentialAnimation {
+ running: true
+ repeat: true
+ NumericAnimation { to: 200-img.height; easing: "easeOutBounce"; duration: 2000 }
+ PauseAnimation { duration: 1000 }
+ NumericAnimation { to: 0; easing: "easeOutQuad"; duration: 1000 }
+ }
+ }
+}
+\endcode
+
+\image propanim.gif
+
+\target states-transitions
+\section1 States and Transitions
+
+\section2 States
+
+QML states describe user interface configurations, including:
+\list
+\o What UI elements are present
+\o The properties of those elements (including how they behave)
+\o What actions are available
+\endlist
+
+A state can also be thought of as a set of batched changes from a default configuration.
+
+Examples of states in modern UI:
+\list
+\o A Contacts application has a 'View Contact' state and an 'Edit Contact' State. In the first state the information presented is static (using labels), and in the second it is editable (using editors).
+\o A button has a pressed and unpressed state. When pressed the text moves down and to the right, and the button has a slightly darker appearance.
+\endlist
+
+In QML:
+\list
+\o Any object can use states.
+\o There is a default state. The default state can be explicitly set.
+\o A state can affect other the properties of other objects, not just the object owning the state (and not just that object's children).
+\endlist
+
+The following example shows a simple use of states. In the default state \c myrect is positioned at 0,0. In the 'moved' state it is positioned at 50,50.
+
+\code
+Item {
+ Rect {
+ id: myrect
+ width: 100
+ height: 100
+ }
+ states: [
+ State {
+ name: "moved"
+ SetProperty {
+ target: myrect
+ property: "x"
+ value: 50
+ }
+ SetProperty {
+ target: myrect
+ property: "y"
+ value: 50
+ }
+ }
+ ]
+}
+\endcode
+
+\section2 Transitions
+
+QML transitions describe animations to perform when state changes occur.
+
+For the previous example, a transition could describe how \c myrect moved from its initial position to its new position:
+
+\code
+transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "x,y"
+ easing: "easeOutBounce"
+ duration: 200
+ }
+ }
+]
+\endcode
+
+QML transitions can use selectors to determine which state changes a transition should apply to:
+
+\code
+Transition {
+ fromState: "*"
+ toState: "Details"
+ ...
+}
+\endcode
+
+Transitions can happen in parallel, in sequence, or in any combination of the two:;
+
+\code
+Transition {
+ fromState: "*"
+ toState: "MyState"
+ reversible: true
+ SequentialAnimation {
+ ColorAnimation {
+ duration: 1000
+ }
+ PauseAnimation {
+ duration: 1000
+ }
+ ParallelAnimation {
+ NumericAnimation {
+ duration: 1000
+ easing: "easeOutBounce"
+ target: box1
+ properties: "x,y"
+ }
+ NumericAnimation {
+ duration: 1000
+ target: box2
+ properties: "x,y"
+ }
+ }
+ }
+}
+\endcode
+
+\section1 Property Behaviors
+
+\note Property behaviors are currently experimental.
+*/
diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc
new file mode 100644
index 0000000..f7eee50
--- /dev/null
+++ b/doc/src/declarative/basictypes.qdoc
@@ -0,0 +1,265 @@
+/*!
+ \page basicqmltypes.html
+ \title Common QML Types
+
+ QML uses a range of property types, which you will see
+ referenced throughout the element documentation. Almost all of them are
+ exactly what you would expect.
+
+ \target basicqmlint
+ \raw HTML
+ <table>
+ <tr><td><div class="qmltype">int</div></td></tr>
+ </table>
+ \endraw
+
+ ints are whole numbers - things like 0, 10 and -20. The possible int
+ values range from around -2000000000 to around 2000000000, although most
+ elements will only accept a reduced range (which they mention in their
+ documentation).
+
+ int's must be specified using the plain old syntax you learned at school -
+ none of that scientific notation nonsense is supported.
+
+ Setting ints looks like this:
+ \code
+ Item { width: 100; height:200 }
+ \endcode
+
+ \target basicqmlbool
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">bool</div></td></tr>
+ </table>
+ \endraw
+
+ bools are a binary true/false value, represented by the strings
+ "true" and "false" in QML.
+
+ Setting bools looks like this:
+ \code
+ Item { focusable: true; clip: false }
+ \endcode
+
+ \note Technically bool treats an empty string, "false" and "0" as false and
+ everything else as true. Seriously, though, use "true" and "false".
+
+ \target basicqmlreal
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">real</div></td></tr>
+ </table>
+ \endraw
+
+ reals are numbers - either whole numbers like ints, or fractional numbers
+ like 1.2 and -29.8.
+
+ Setting reals looks like this:
+ \code
+ Item { x: -10; y: 100.8 }
+ \endcode
+
+ \note In QML all reals are stored in single precision, \l {http://en.wikipedia.org/wiki/IEEE_754}{IEEE floating point} format.
+
+ \target basicqmlstring
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">string</div></td></tr>
+ </table>
+ \endraw
+
+ strings are free form text, like "hello world", "QML is cool" and
+ anything else you can think of.
+
+ Setting a string looks like this:
+ \code
+ Text { text: "Hello world!" }
+ \endcode
+
+ \raw HTML
+ \endraw
+
+ \target basicqmlcolor
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">color</div></td></tr>
+ </table>
+ \endraw
+
+ Colors are most commonly specified as an \l {http://www.w3.org/TR/SVG/types.html#ColorKeywords}{SVG color name}. These names include colors like
+ "red", "green" and "lightsteelblue".
+
+ If the color you want isn't part of this list, colors can also be specified
+ in hexidecimal triplets or quads that take the form \c "#RRGGBB" and
+ \c "#AARRGGBB" respectively. For example, the color red corresponds to a
+ triplet of \c "#FF0000" and a slightly transparent blue to a quad of
+ \c "#800000FF".
+
+ Setting a color looks like this:
+ \code
+ Rect { color: "steelblue" }
+ Rect { color: "#FF0000" }
+ Rect { color: "#800000FF" }
+ \endcode
+
+ \target basicqmlpoint
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">point</div></td></tr>
+ </table>
+ \endraw
+
+ Points are specified in \c "x,y" format.
+
+ Setting a point looks like this:
+ \code
+ Widget { pos: "50,50" }
+ \endcode
+
+ \target basicqmlsize
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">size</div></td></tr>
+ </table>
+ \endraw
+
+ Sizes are specified in \c "widthxheight" format.
+
+ Setting a size looks like this:
+ \code
+ Widget { size: "50x50" }
+ \endcode
+
+ \target basicqmlrectangle
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">rectangle</div></td></tr>
+ </table>
+ \endraw
+
+ Rectangles are specified in \c "x,y,widthxheight" format.
+
+ Setting a rectangle looks like this:
+ \code
+ Widget { geometry: "50,50,100x100" }
+ \endcode
+
+ \target basicqmldate
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">date</div></td></tr>
+ </table>
+ \endraw
+
+ Dates are specified in \c "YYYY-MM-DD" format.
+
+ Setting a date looks like this:
+ \code
+ DatePicker { minDate: "2000-01-01"; maxDate: "2020-12-31" }
+ \endcode
+
+ \target basicqmltime
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">time</div></td></tr>
+ </table>
+ \endraw
+
+ Times are specified in \c "hh:mm:ss" format.
+
+ Setting a time looks like this:
+ \code
+ TimePicker { time: "14:22:15" }
+ \endcode
+
+ \target basicqmlfont
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">font</div></td></tr>
+ </table>
+ \endraw
+
+ The font type has components:
+ \list
+ \o string font.family
+ \o bool font.bold
+ \o bool font.italic
+ \o real font.size
+ \endlist
+
+ Setting a font looks like this:
+ \code
+ Text { font.family: "Helvetica"; font.size: 13; font.bold: true }
+ \endcode
+
+ \target basicqmlaction
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">action</div></td></tr>
+ </table>
+ \endraw
+
+ The action type has all the properties of QAction, in particular:
+ \list
+ \o slot action.trigger - invoke the action
+ \o bool action.enabled - true if the action is enabled
+ \o string action.text - the text associated with the action
+ \endlist
+
+ Actions are used like this:
+
+ \code
+ MouseRegion { onClicked: someitem.someaction.trigger() }
+ State { name: "enabled"; when: someitem.someaction.enabled=='true' }
+ Text { text: someitem.someaction.text }
+ \endcode
+
+ \target basicqmlany
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">any</div></td></tr>
+ </table>
+ \endraw
+
+ The any type can accept any basic type, object or list. Generally this
+ is only used in very special cases. The documentation for elements that
+ use the any type will explain the constraints in that particular case.
+
+ \target basicqmllist
+ \raw HTML
+ <br>
+ <table>
+ <tr><td><div class="qmltype">Lists</div></td></tr>
+ </table>
+ \endraw
+
+ While not technically a basic type, QML also supports lists of object
+ types. When used from QML, the engine automatically appends each value to the
+ list.
+
+ For example, the \l Item class has a children list property
+ that can be used like this:
+ \code
+ Item {
+ children [
+ Item { id: child1 },
+ Rect { id: child2 },
+ Text { id: child3 }
+ ]
+ }
+ \endcode
+ \c child1, \c child2 and \c child3 will all be added to the children list
+ in the order in which they appear.
+*/
diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/binding.qdoc
new file mode 100644
index 0000000..2920d51
--- /dev/null
+++ b/doc/src/declarative/binding.qdoc
@@ -0,0 +1,110 @@
+/*!
+\page binding.html
+\title Data Binding
+\target binding
+
+Data binding provides a declarative way of specifying the data associated with objects, as well as the relationship between data of different objects. For example, you could bind the text of a label to the value of a slider: as the value of the slider changed, the label would be automatically updated with the new value.
+
+Bindings are created in Qml when an expression is assigned to a property. For example, the following produces two Rects of equal size (\c rect2 is bound to the size of \c rect1):
+\code
+Rect { id: rect1; width: 100; height: 100 }
+Rect { id: rect2; width: rect1.width; height: rect1.height }
+\endcode
+
+There is also a special \l Bind element, which is typically used to bind from the UI to the underlying UI model (see \l {Passing Data Between C++ and Qml} for an example of this). The bindings above could be expressed using the \l Bind element as:
+
+\code
+Bind { target: rect2; property: "width"; value: rect1.width }
+Bind { target: rect2; property: "height"; value: rect1.height }
+\endcode
+
+In addition to binding directly to a property, you can also bind to the results of expressions involving properties. For example:
+\code
+Text { text: contact.firstname + ' ' + contact.lastname }
+Image { source: if (contact.gender == "female") {"pics/female.png"} else {"pics/male.png"} }
+\endcode
+
+Relevant items can also be bound to the contents of a model - see \l ListView for an example of this.
+
+Data can be bound to C++ objects - see \l {C++ Data Binding}.
+*/
+
+/*!
+\page qtbinding.html
+\target qtbinding
+\title C++ Data Binding
+
+The QML mechanisms of \l {Data Binding} can also be used to bind Qt C++ objects.
+
+The data binding framework is based on Qt's property system (see the Qt documentation for more details on this system). If a binding is meant to be dynamic (where changes in one object are reflected in another object), \c NOTIFY must be specified for the property being tracked. If \c NOTIFY is not specified, any binding to that property will be an 'intialization' binding (the tracking object will be updated only once with the initial value of the tracked object).
+
+Relevant items can also be bound to the contents of a Qt model. For example, ListView can make use of data from a QListModelInterface-derived model. (QListModelInterface is part of the next generation Model/View architecture being developed for Qt.)
+
+
+\section1 Passing Data Between C++ and Qml
+
+Data binding provides one method of data transfer between C++ and Qml.
+
+For example, lets say you want to implement a slider in Qml that changes the screen brightness of the device it is running on. You would start by declaring a brightness property on your QObject-derived class:
+\code
+class MyScreen : public QObject
+{
+ Q_OBJECT
+public:
+ MyScreen(QObject *parent=0);
+
+ Q_PROPERTY(int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged);
+ int brightness() const;
+ void setBrightness(int b);
+ ...
+
+signals:
+ void brightnessChanged();
+
+private:
+ int m_brightness;
+};
+
+int brightness() const
+{
+ return m_brightness;
+}
+
+void setBrightness(int b)
+{
+ if (b != m_brightness) {
+ m_brightness = b;
+ emit brightnessChanged();
+
+ //set device brightness
+ ...
+ }
+}
+\endcode
+
+\note One important thing to keep in mind is that the changed signal should only be emitted when there is a real change ( \c b \c != \c m_brightness ), or you may get an infinite loop.
+
+Next, make an instance of this class visible to the Qml bind engine:
+\code
+QFxView *view = new QFxView;
+view->setUrl("MyUI.qml");
+
+MyScreen *screen = new MyScreen;
+QmlBindContext *ctxt = view->rootContext();
+ctxt->setContextProperty("screen", screen);
+
+view->execute();
+\endcode
+
+\note Bindings must be made after setUrl() but before execute().
+
+Finally, in Qml you can make the appropriate bindings, so in \c "MyUI.qml":
+
+\code
+Slider { value: screen.brightness }
+Bind { target: screen; property: "brightness"; value: slider.value }
+\endcode
+
+The \l QBindableMap class provides a convenient way to make data visible to the bind engine.
+
+*/
diff --git a/doc/src/declarative/components.qdoc b/doc/src/declarative/components.qdoc
new file mode 100644
index 0000000..d7a4ba6
--- /dev/null
+++ b/doc/src/declarative/components.qdoc
@@ -0,0 +1,92 @@
+/*!
+\page components.html
+\target components
+\title Components
+
+A \bold component is a reusable, encapsulated Qml element with a well-defined interface.
+
+Writing and using components allows you to:
+\list
+\o Reuse sections of Qml without copy-and-paste.
+\o Have consistent Look and Feel between different parts of your UI.
+\o Create new Qml elements without writing a new C++ class. (See \l {cppitem}{Creating Qml elements in C++})
+\endlist
+
+Components are placed in \e <Name>.qml files, allowing \e <Name> to then be used as a tag
+elsewhere. For example, if you have a Slider.qml file, you can then use \c {Slider { ... }} to
+make a slider, just as if it was a built-in type.
+
+Components may be collected into \l {qmlmodules}{modules}.
+
+\section1 Example: Creating a MyButton Component
+
+This example describes how to create a component from an existing snippet of Qml.
+
+Assume you have an existing UI with a single 'Save' button, defined as follows:
+
+\code
+Image {
+ source: "pics/button-background.png"
+ Text {
+ text: "Save"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClick: { saveData() }
+ }
+}
+\endcode
+
+For the next release, you plan to add 'Cancel' and 'Reset' buttons. Rather than copying and pasting the above markup, you can create a component:
+
+\list 1
+\o Create a file called MyButton.qml, and copy the relevant Qml snippet into that file.
+\o Make some minor changes to define the component's interface:
+
+\code
+Image {
+ property string label
+ signal clicked
+ source: "pics/button-background.png"
+ Text {
+ text: parent.label
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClick: { parent.click.emit() }
+ }
+}
+\endcode
+
+The \a label property and \a click signal that were added effectively become part of the 'public API' of the MyButton component. In a similar manner, the Text and MouseRegion elements become invisible to anyone using the component. Note that the Text element now binds in its data from \a label, and the MouseRegion emits a generic signal.
+
+\o The component can now be used elsewhere as MyButton:
+
+\code
+MyButton { label: "Save"; onClicked: saveData() }
+...
+MyButton { label: "Cancel"; onClicked: cancelData() }
+...
+MyButton { label: "Reset"; onClicked: resetData() }
+\endcode
+
+\endlist
+
+\section1 Placing .qml Files
+
+When one component refers to a another, the second must be found either in the same directory
+as the first, or in a directory imported using the \c import statement:
+
+\code
+import "library"
+\endcode
+
+\section1 Namespaces
+
+Namespaces for QML will be supported in Qt 4.6.
+
+*/
diff --git a/doc/src/declarative/cppitem.qdoc b/doc/src/declarative/cppitem.qdoc
new file mode 100644
index 0000000..d212a5e
--- /dev/null
+++ b/doc/src/declarative/cppitem.qdoc
@@ -0,0 +1,127 @@
+/*!
+\page cppitem.html
+\target cppitem
+\title C++ Components
+
+\section1 Making a C++ object available in QML
+
+In QML, the item types and properties correspond to Qt objects and properties. Thus, any Qt object
+can potentially be used as an item in QML. More specifically, to make an object available in QML,
+it should:
+\list
+\o Be a subclass of QObject.
+\o Provide a default constructor.
+\o Declare Q_PROPERTYs.
+\o Be registered via the QML_DECLARE_TYPE and QML_DEFINE_TYPE macros.
+\endlist
+
+\section2 Declaring Q_PROPERTYs
+\target properties
+
+Properties of QObject subclasses are available as properties in QML.
+Like any QObject, these properties are defined by the Q_PROPERTY
+macro in the header file.
+
+Properties should have a NOTIFY function if they can change dynamically and
+if any useful response could be made to them changing in another object. Almost
+all properties will thus need a NOTIFY function.
+
+\code
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged);
+ qreal scale() const;
+ void setScale(qreal);
+ ...
+ signals: void scaleChanged();
+\endcode
+
+The property types currently supported by QML are:
+\list
+\o int
+\o qreal
+\o QString
+\o QColor
+\o QDate, QTime, and QDateTime
+\o QSize and QSizeF
+\o QPoint and QPointF
+\o QRect and QRectF
+\o QPixmap
+\o QIcon
+\o enums registered with Q_ENUMS
+\o flags registered with Q_FLAGS
+\o QVariant
+\o QObject* (or subclass)
+\endlist
+
+Custom property types that provide string-to-type conversion can be used as well, by:
+\list
+\o Registering them as a metatype (Q_DECLARE_METATYPE() and qRegisterMetaType())
+\o Registering a string-to-type convertor function (QML::addCustomStringConvertor()).
+\endlist
+
+\section2 Registering your type
+\target register
+
+In order for your type to be usable in QML, you must register it:
+
+\code
+QML_DECLARE_TYPE(TypeName);
+QML_DEFINE_TYPE(TypeName,QmlName);
+\endcode
+
+These macros make the C++ \e TypeName available from the declarative markup language under the name \e QmlName.
+Of course there's nothing stopping you using the same name for both the C++ and the QML name!
+
+For example:
+\code
+QML_DECLARE_TYPE(MyCircle);
+QML_DEFINE_TYPE(MyCircle,Circle);
+\endcode
+would make the \e MyCircle class accessable though the \c Circle type in QML.
+
+
+\section1 Creating a new 'Fx' item in C++
+
+You can create a new type of 'Fx' item by:
+\list 1
+\o Creating a subclass of QFxItem,
+\o Adding Q_PROPERTYs appropriate for your item (see \l {properties}{Properties}),
+\o Reimplementing the relevant paint functions,
+\o Registering the type with the QML_DECLARE_TYPE and QML_DEFINE_TYPE macros (see \l {register}{Register}).
+\endlist
+
+\section2 Creating a subclass of QFxItem
+
+To add a new type, you first must add a new C++ class derived from QFxItem.
+You may of course extend existing QFxItem subclasses.
+
+One existing subclass is QFxPainted, which provides
+a simple cached-image painting model.
+
+\section2 Reimplementing paint functions
+
+Two alternative painters are available, offering
+different levels of performance and functionality:
+QPainter, GLPainter.
+
+You can choose to subclass QFxPainted rather than QFxItem,
+and then implement the virtual method:
+
+\code
+ void paint(QPainter *painter);
+\endcode
+
+This paints into an offscreen pixmap which is then painted to the display (transformed,
+etc. as needed). The cost of this offscreen pixmap should be carefully considered, as
+should the specific performance of the painting done in the paint function.
+
+If you require more control, subclass QFxItem instead.
+QFxItem subclasses must implement both simple software canvas painting
+and GL painting:
+\list
+\o \c QFxItem::paintContents(QPainter &) for the simple software canvas,
+\o \c QFxItem::paintGLContents(GLPainter &) for OpenGL.
+\endlist
+
+See the documentation of those functions for detailed subclassing notes.
+
+*/
diff --git a/doc/src/declarative/effects.qdoc b/doc/src/declarative/effects.qdoc
new file mode 100644
index 0000000..8350dc4
--- /dev/null
+++ b/doc/src/declarative/effects.qdoc
@@ -0,0 +1,29 @@
+/*!
+\page effects.html
+\target qmleffects
+\title Visual Effects
+
+\section1 Basic Effects
+
+\list
+\o Scaling (\l Item \bold scale property)
+\o Opacity (\l Item \bold opacity property)
+\o Rotation (\l Item \bold rotation property, and Rotation3D)
+\o Affine Transforms (\l Squish)
+\endlist
+
+\section1 Advanced Effects
+
+These effects are currently only supported by the OpenGL canvas
+backend. Support for other backends may be added if the performance
+can be made acceptable.
+
+\list
+\o \l Shadow
+\o \l Blur
+\o \l Reflection
+\o \l Highlight
+\o \l Particles
+\endlist
+
+*/
diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc
new file mode 100644
index 0000000..3298699
--- /dev/null
+++ b/doc/src/declarative/elements.qdoc
@@ -0,0 +1,163 @@
+/*!
+\page elements.html
+\target elements
+\title Qml Elements
+
+The following table lists the Qml elements provided by the Qt Declarative module.
+
+\bold {Standard Qt Declarative Elements}
+
+\table 80%
+\header
+\o \bold {States}
+\o \bold {Animation and Transitions}
+\o \bold {Working with Data}
+\o \bold {Utility}
+\row
+
+\o
+\list
+\o \l State
+\o \l SetProperty
+\o \l SetProperties
+\o \l ParentChange
+\o \l RunScript
+\endlist
+
+\o
+\list
+\o \l NumericAnimation
+\o \l ColorAnimation
+\o \l VariantAnimation
+\o \l PauseAnimation
+\o \l SequentialAnimation
+\o \l ParallelAnimation
+\o \l SetPropertyAction
+\o \l ParentChangeAction
+\o \l Transition
+\o \l Behaviour
+\o \l Follow
+\endlist
+
+\o
+\list
+\o \l Bind
+\o \l ListModel
+\o \l XmlListModel
+\o \l SqlQuery, \l SqlConnection, and \l SqlBind
+\o \l DateTimeFormatter
+\o \l NumberFormatter
+\endlist
+
+\o
+\list
+\o \l Script
+\o \l Connection
+\o \l Component
+\endlist
+\endtable
+
+\bold {Fluid UI Primitives}
+
+\table 80%
+\header
+\o \bold {Basic Visual Items}
+\o \bold {Basic Interaction Items}
+\o \bold {Widgets}
+\o \bold {Utility}
+
+\row
+\o
+\list
+\o \l Item
+\o \l Image
+\o \l Text
+\o \l TextEdit
+\o \l Rect
+\o \l AnimatedImage
+\o \l BlendedImage
+\endlist
+
+\o
+\list
+\o \l MouseRegion
+\o \l KeyActions
+\o \l FocusPanel
+\o \l FocusRealm
+\o \l KeyProxy
+\endlist
+
+\o
+\list
+\o \l Flickable
+\o \l Flipable
+\o \l WebView
+\endlist
+
+\o
+\list
+\o \l Repeater
+\o \l ContentWrapper
+ \list
+ \o \l Content
+ \endlist
+\o \l ComponentInstance
+\o \l WidgetContainer
+\endlist
+
+\header
+\o \bold {Views}
+\o \bold {Layouts}
+\o \bold {Transforms}
+\o \bold {Effects}
+
+\row
+\o
+
+\target xmlViews
+\list
+\o \l ListView
+\o \l GridView
+\o \l PathView
+ \list
+ \o \l Path
+ \list
+ \o \l PathLine
+ \o \l PathQuad
+ \o \l PathCubic
+ \o \l PathAttribute
+ \o \l PathPercent
+ \endlist
+ \endlist
+\endlist
+
+\o
+\list
+\o \l VerticalLayout
+\o \l HorizontalLayout
+\o \l GridLayout
+\endlist
+
+\o
+\list
+\o \l Rotation
+\o \l Squish
+\o \l Rotation3D
+\endlist
+
+\o
+\list
+\o \l Shadow
+\o \l Reflection
+\o \l Blur
+\o \l Highlight
+\o \l Particles
+ \list
+ \o \l ParticleMotionLinear
+ \o \l ParticleMotionGravity
+ \o \l ParticleMotionWander
+ \endlist
+\endlist
+\endtable
+
+*/
diff --git a/doc/src/declarative/examples.qdoc b/doc/src/declarative/examples.qdoc
new file mode 100644
index 0000000..31c8a5d
--- /dev/null
+++ b/doc/src/declarative/examples.qdoc
@@ -0,0 +1,30 @@
+/*!
+\page qmlexamples.html
+\target qmlexamples
+\title QML Examples
+
+A \l {qmlviewer}{viewer} application is included that allows you to quickly explore many of the
+examples. It has some useful options, revealed by:
+
+\code
+ bin/qmlviewer -help
+\endcode
+
+There are several illustrative QML examples available. From your build
+directory,
+
+\code
+ bin/qmlviewer $QT_SOURCE_DIR/demos/declarative/flickr/flickr.qml
+\endcode
+
+Many other simple examples can be found under the \c examples/declarative sub
+directory. Some can be run directly using the viewer like those above, and
+others require you to build and run an executable.
+
+More sophisticated demos of large applications can be found under the \c demos/declarative
+sub directory. These are intended to show more integrated functionality rather than
+to be instructive on specific elements.
+
+Finally, check out the \l {tutorial} to learn a little more about writing your
+own QML-based applications.
+*/
diff --git a/doc/src/declarative/focus.qdoc b/doc/src/declarative/focus.qdoc
new file mode 100644
index 0000000..e5c181d
--- /dev/null
+++ b/doc/src/declarative/focus.qdoc
@@ -0,0 +1,262 @@
+/*!
+\target qmlfocus
+\page qmlfocus.html
+\title Fluid UI Keyboard Focus
+
+When a key is pressed or released, a key event is generated and delivered to the
+focused fluid UI \l Item. To facilitate the construction of reusable components
+and to address some of the cases unique to fluid UIs, the fluid UI atoms add a
+"realm" based extension to Qt's traditional keyboard focus model.
+
+\section1 Key Handling Overview
+
+When the user presses or releases a key, the following occurs:
+\list 1
+\o Qt receives the key action and generates a key event.
+\o If the Qt widget containing the fluid UI scene has focus, the key event is delivered to the fluid UI scene. Otherwise, regular Qt key handling continues.
+\o The key event is delivered by the scene to the fluid UI \l Item with \e {active focus}. If no fluid UI \l Item has \e {active focus}, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues.
+\o If the fluid UI \l Item with \e {active focus} accepts the key event, propagation stops. Otherwise the event is "bubbled up", by recursively passing it to each \l Item's parent until either the event is accepted, or the root \l Item is reached.
+
+If the \c {Rect} element in the following example has active focus and the \e A key is pressed, it will bubble up to the \c {KeyActions}. However, pressing the \e B key will bubble up to the root item and thus subsequently be \l {QEvent::ignore()}{ignored}.
+
+\code
+Item {
+ KeyActions {
+ keyA: "print('Key A was pressed')"
+ Rect {}
+ }
+}
+\endcode
+
+\o If the root \l Item is reached, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues.
+
+\endlist
+
+\section1 Querying the Active Focus Item
+
+Whether or not an \l Item has \e {active focus} can be queried through the
+read-only property \c {Item::activeFocus}. For example, here we have a \l Text
+element whose text is determined by whether or not it has \e {active focus}.
+
+\code
+Text {
+ text: activeFocus ? "I have active focus!" : "I do not have active focus"
+}
+\endcode
+
+\section1 Acquiring Focus and Focus Realms
+
+An \l Item requests focus by setting the \c {Item::focus} property to true.
+
+For very simple cases simply setting the \c {Item::focus} property is sometimes
+sufficient. If we run the following example in the \c qmlviewer, we see that
+the \c {KeyActions} element has \e {active focus} and pressing the
+\e A, \e B, or \e C keys modifies the text appropriately.
+
+\table
+\row
+\o \code
+ Rect {
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: MyText }
+ KeyActions {
+ focus: true
+ keyA: "MyText.text = 'Key A was pressed'"
+ keyB: "MyText.text = 'Key B was pressed'"
+ keyC: "MyText.text = 'Key C was pressed'"
+ }
+ }
+\endcode
+\o \image declarative-qmlfocus1.png
+\endtable
+
+However, were the above example to be used as a self-contained component, this
+simple use of the \c {Item::focus} property is no longer sufficient. The left
+hand side of the following table shows what we would like to be able to write.
+Here we create two instances of our previously defined component, and set the
+second one to have focus. The intention is that when the \e A, \e B, or \e C
+keys are pressed, the second of the two components receives the event and
+reponds accordingly.
+
+\table
+\row
+\o \code
+Rect {
+ color: "red"; width: 240; height: 55
+ MyWidget {}
+ MyWidget { y: 30; focus: true }
+}
+\endcode
+\o \code
+Rect {
+ color: "red"; width: 240; height: 55
+ Rect {
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: MyText }
+ KeyActions {
+ focus: true
+ keyA: "MyText.text = 'Key A was pressed'"
+ keyB: "MyText.text = 'Key B was pressed'"
+ keyC: "MyText.text = 'Key C was pressed'"
+ }
+ }
+ Rect {
+ y: 30; focus: true
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: MyText }
+ KeyActions {
+ focus: true
+ keyA: "MyText.text = 'Key A was pressed'"
+ keyB: "MyText.text = 'Key B was pressed'"
+ keyC: "MyText.text = 'Key C was pressed'"
+ }
+ }
+}
+\endcode
+\endtable
+
+The right hand side of the example shows the expanded code - the equivalent QML
+without the use of the component \c {MyWidget}. From this, the problem is
+evident - there are no less than three elements that have the \c {Item::focus}
+property set to true. Ultimately only one element can have focus, and the
+system has to decide which on. In this case the first appearance of the
+\c {Item::focus} property being set to true on line 4 is selected, and the value
+of \c {Item::focus} in the other two instances is reverted back to false. This
+is exactly the opposite of what was wanted!
+
+This problem is fundamentally one of visibility. The \c {MyWidget}
+components each set their \c {KeyActions} as focused as that is all they can
+do - they don't know how they are going to be used, but they do know that when
+they're in use their \c {KeyActions} element is what needs focus. Likewise
+the code that uses the \c {MyWidget}'s sets the second \c {MyWidget} as
+focused because, while it doesn't know exactly how the \c {MyWidget} is
+implemented, it knows that it wants the second one to be focused. No one piece
+of code knows everything about the other, which is exactly how it should be.
+
+To solve this problem - allowing components to care about what they know about
+and ignore everything else - the fluid UI atoms introduce a concept known as a
+\e {focus realm}. For existing Qt users, a \e {focus realm} is like an
+automatic focus proxy. A \e {focus realm} is created using the \l FocusRealm
+element.
+
+In the next example, a \l FocusRealm is added to the component, and the visual
+result shown.
+
+\table
+\row
+\o \code
+FocusRealm {
+ width: 240; height: 25
+ Rect {
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: MyText }
+ KeyActions {
+ focus: true
+ keyA: "MyText.text = 'Key A was pressed'"
+ keyB: "MyText.text = 'Key B was pressed'"
+ keyC: "MyText.text = 'Key C was pressed'"
+ }
+ }
+}
+\endcode
+\o \image declarative-qmlfocus2.png
+\endtable
+
+Conceptually \e {focus realms} are quite simple.
+\list
+\o Within each \e {focus realm} one element may have \c {Item::focus} set to true. If more than one \l Item has the \c {Item::focus} property set, the first is selected and the others are unset, just like when there are no \e {focus realms}.
+\o When a \e {focus realm} receives \e {active focus}, the contained element with \c {Item::focus} set (if any) also gets \e {active focus}. If this element is
+also a \l FocusRealm, the proxying behaviour continues. Both the
+\e {focus realm} and the sub-focused item will have \c {Item::activeFocus} set.
+\endlist
+
+So far the example has the second component statically selected. It is trivial
+now to extend this component to make it clickable, and add it to the original
+application. We still set a one of the widgets as focused by default, but from
+then on clicking the either one gives it focus.
+
+\table
+\row
+\o \code
+Rect {
+ color: "red"; width: 240; height: 55
+ MyClickableWidget {}
+ MyClickableWidget { y: 30; focus: true }
+}
+\endcode
+\o \code
+FocusRealm {
+ id: Page; width: 240; height: 25
+ MyWidget { focus: true }
+ MouseRegion { anchors.fill: parent; onClicked: { Page.focus = true } }
+}
+\endcode
+\endtable
+
+\image declarative-qmlfocus3.png
+
+When a fluid UI atom explicitly relinquishes focus (by setting its
+\c {Item::focus} property to false while it has \e {active focus}), the system
+does not automatically select another element to receive focus. That is, it
+is possible for there to be no currently \e {active focus}.
+
+\section1 Advanced uses of Focus Realms
+
+Focus realms allow focus to allocation to be easily partitioned. Several
+fluid UI atoms use it to this effect.
+
+\l ListView, for example, is itself a focus realm. Generally this isn't
+noticable as \l ListView doesn't usually have manually added visual children.
+By being a focus realm, \l ListView can focus the current list item without
+worrying about how that will effect the rest of the application. This allows
+the current item delegate to react to key presses.
+
+This contrived example shows how this works. Pressing the \c Return key will
+print the name of the current list item.
+
+\table
+\row
+\o \code
+Rect {
+ color: "lightsteelblue"; width: 240; height: 320
+
+ ListView {
+ id: MyView; anchors.fill: parent; focus: true
+ model: ListModel {
+ ListElement { name: "Bob" }
+ ListElement { name: "John" }
+ ListElement { name: "Michael" }
+ }
+ delegate: FocusRealm {
+ width: contents.width; height: contents.height
+ Text { text: name }
+ KeyActions { return: "print(name)"; focus: true }
+ }
+ }
+}
+\endcode
+\o \image declarative-qmlfocus4.png
+\endtable
+
+While the example is simple, there's a lot going on behind the scenes. Whenever
+the current item changes, the \l ListView sets the delegate's \c {Item::focus}
+property. As the \l ListView is a \e {focus realm}, this doesn't effect the
+rest of the application. However, if the \l ListView itself has
+\e {active focus} this causes the delegate itself to receive \e {active focus}.
+In this example, the root element of the delegate is also a \e {focus realm},
+which in turn gives \e {active focus} to the \c {KeyActions} element that
+actually performs the work of handling the \e {Return} key.
+
+All of the fluid UI view classes, such as \l PathView and \l GridView, behave
+in a similar mannor to allow key handling in their respective delegates.
+
+\section1 Focus Panels
+
+Traditional UIs are composed of many top-level windows. Windows actually
+perform two tasks - they act as the visual bounds for a widget, and they segment
+focus. Each window has a separate focused widget, that becomes (to mix
+terminologies) the \e {active focus} widget when the window is the active
+window.
+
+### Focus panels do basically the same thing.
+*/
diff --git a/doc/src/declarative/measuring-performance.qdoc b/doc/src/declarative/measuring-performance.qdoc
new file mode 100644
index 0000000..2387335
--- /dev/null
+++ b/doc/src/declarative/measuring-performance.qdoc
@@ -0,0 +1,81 @@
+/*!
+\page optimizing-performance.html
+\target optimizing-performance
+\title Optimizing Performance
+
+The Qt Declarative module includes several tools to help measure performance.
+
+\section1 Performance Logging
+
+The declarative module uses the functionality provided by QPerformanceLog to log performance information. To see this information you can add the following to src.pro:
+
+\code
+DEFINES += Q_ENABLE_PERFORMANCE_LOG
+\endcode
+
+The performance information will be printed to screen on a QML application startup, or when running the viewer can be forced at anytime by pressing 'F3' on the keyboard.
+
+Additional logging can be enabled by adding the relevant categories to qfxperf.h and qfxperf.cpp.
+
+For example, to measure the cost of calculating the size of a text item, you would first define a TextSize category by adding the following:
+
+\code
+//in qfxperf.h
+Q_DECLARE_PERFORMANCE_METRIC(TextSize);
+
+//in qfxperf.cpp
+Q_DEFINE_PERFORMANCE_METRIC(TextSize, "Text Size Calculation");
+\endcode
+
+You could then use this category in the code:
+
+\code
+void QFxText::updateSize()
+{
+ QFxPerfTimer<QFxPerf::TextSize> perf;
+ ...
+}
+\endcode
+
+Because there is no cost for a QFxPerfTimer when Q_ENABLE_PERFORMANCE_LOG is not defined, this line can persist in the code and be used to help detect performance bottlenecks and regressions. See the QPerformanceLog documentation for more information on this performance framework.
+
+\section1 FPS Measurements
+
+When running the viewer, pressing 'F2' on the keyboard while a QML program is running will cause information on cost-per-frame and frames-per-second (FPS) to be printed to the console.
+
+The information printed includes:
+\list
+\o \e repaint(): the total time spent painting.
+\o \e paint(): the time spent by Qt painting.
+\o \e timeBetweenFrames: the total time spent per frame. This number minus repaint() gives a good idea of how much time is spent on things besides painting. A high number here with a low number for repaint() indicates expensive calculations happening each frame.
+\endlist
+
+\section1 Improving Performance
+
+The following tips can help decrease startup time for QML-based appications.
+
+\section2 Images
+
+\list
+\o Use jpg instead of png for photo-like images. On the N810, this can save 150ms for a large (320x480) image.
+
+\o If you are configuring Qt, configure out any image plugins you don't plan to support (mng and svg are the most expensive). On the N810, this can save 75-100ms startup time. For example:
+
+\code
+configure -no-libmng -no-svg -no-libtiff
+\endcode
+
+\o In some cases running pngcrush, optipng, gifsicle or other similar tools can give some improvement.
+
+We are also investigating support for the loading of uncompressed images. This will provide opportunites to decrease startup time at the cost of increased storage space.
+\endlist
+
+\section2 Fonts
+
+\list
+\o Use qpf instead of ttf. When using multiple font sizes and weights on the N810, this can save 125ms startup time compared to a ttf 'clean' run, and 40-50ms on subsequent runs (ttfs are shared by open applications).
+\endlist
+
+*/
+
+*/
diff --git a/doc/src/declarative/modules.qdoc b/doc/src/declarative/modules.qdoc
new file mode 100644
index 0000000..5933223
--- /dev/null
+++ b/doc/src/declarative/modules.qdoc
@@ -0,0 +1,22 @@
+/*!
+\page qmlmodules.html
+\target qmlmodules
+\title Modules of Components
+
+A \bold module is a collection of \l Components.
+
+To use a module, include the following statement at the begining
+of your QML:
+
+\code
+import "path"
+\endcode
+
+This allows all components defined in the directory \c path to be used in
+the component where this statement appears.
+
+Currently, \c path may only be a directory relative to the directory containing
+the component issuing the import.
+
+The import statement cannot be used by remote content.
+*/
diff --git a/doc/src/declarative/pics/3d-axis.png b/doc/src/declarative/pics/3d-axis.png
new file mode 100644
index 0000000..1a587ff
--- /dev/null
+++ b/doc/src/declarative/pics/3d-axis.png
Binary files differ
diff --git a/doc/src/declarative/pics/3d-rotation-axis.png b/doc/src/declarative/pics/3d-rotation-axis.png
new file mode 100644
index 0000000..1b17261
--- /dev/null
+++ b/doc/src/declarative/pics/3d-rotation-axis.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewHighlight.png b/doc/src/declarative/pics/ListViewHighlight.png
new file mode 100644
index 0000000..02bf51d
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewHighlight.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewHorizontal.png b/doc/src/declarative/pics/ListViewHorizontal.png
new file mode 100644
index 0000000..4633a0e
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewHorizontal.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewSections.png b/doc/src/declarative/pics/ListViewSections.png
new file mode 100644
index 0000000..9270126
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewSections.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewVertical.png b/doc/src/declarative/pics/ListViewVertical.png
new file mode 100644
index 0000000..e0b23d9
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewVertical.png
Binary files differ
diff --git a/doc/src/declarative/pics/anchors.svg b/doc/src/declarative/pics/anchors.svg
new file mode 100644
index 0000000..08b00ed
--- /dev/null
+++ b/doc/src/declarative/pics/anchors.svg
@@ -0,0 +1,92 @@
+<?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://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"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg1910"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ inkscape:export-filename="/home/mbrasser/work/Kinetic/ngui/doc/src/pics/anchors_example2.png"
+ inkscape:export-xdpi="189.65207"
+ inkscape:export-ydpi="189.65207"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="anchors.svg">
+ <defs
+ id="defs1912" />
+ <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="1.979899"
+ inkscape:cx="431.57095"
+ inkscape:cy="413.38853"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1386"
+ inkscape:window-height="971"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata1915">
+ <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:none;fill-opacity:1;stroke:black;stroke-width:0.52033526;stroke-miterlimit:4;stroke-dasharray:1.04067054, 0.52033527;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2807"
+ width="36.245155"
+ height="32.204544"
+ x="390.23157"
+ y="574.62024" />
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:black;stroke-width:0.44547796;stroke-miterlimit:4;stroke-dasharray:0.89095592, 0.44547796;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2809"
+ width="59.048447"
+ height="14.601732"
+ x="430.82993"
+ y="574.9483" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="399.40982"
+ y="594.76312"
+ id="text3696"><tspan
+ sodipodi:role="line"
+ id="tspan3698"
+ x="399.40982"
+ y="594.76312">pic</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="445.84048"
+ y="586.5423"
+ id="text3700"><tspan
+ sodipodi:role="line"
+ id="tspan3702"
+ x="445.84048"
+ y="586.5423">label</tspan></text>
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/animatedimageitem.gif b/doc/src/declarative/pics/animatedimageitem.gif
new file mode 100644
index 0000000..85c3cb5
--- /dev/null
+++ b/doc/src/declarative/pics/animatedimageitem.gif
Binary files differ
diff --git a/doc/src/declarative/pics/axisrotation.png b/doc/src/declarative/pics/axisrotation.png
new file mode 100644
index 0000000..409a9e9
--- /dev/null
+++ b/doc/src/declarative/pics/axisrotation.png
Binary files differ
diff --git a/doc/src/declarative/pics/blur_example.png b/doc/src/declarative/pics/blur_example.png
new file mode 100644
index 0000000..763b112
--- /dev/null
+++ b/doc/src/declarative/pics/blur_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/content.png b/doc/src/declarative/pics/content.png
new file mode 100644
index 0000000..47a98ac
--- /dev/null
+++ b/doc/src/declarative/pics/content.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus1.png b/doc/src/declarative/pics/declarative-qmlfocus1.png
new file mode 100644
index 0000000..fd05146
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus1.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus2.png b/doc/src/declarative/pics/declarative-qmlfocus2.png
new file mode 100644
index 0000000..a946e2c
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus2.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus3.png b/doc/src/declarative/pics/declarative-qmlfocus3.png
new file mode 100644
index 0000000..ba55f76
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus3.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus4.png b/doc/src/declarative/pics/declarative-qmlfocus4.png
new file mode 100644
index 0000000..e21f2a6
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus4.png
Binary files differ
diff --git a/doc/src/declarative/pics/edge1.png b/doc/src/declarative/pics/edge1.png
new file mode 100644
index 0000000..f4bc16d
--- /dev/null
+++ b/doc/src/declarative/pics/edge1.png
Binary files differ
diff --git a/doc/src/declarative/pics/edge2.png b/doc/src/declarative/pics/edge2.png
new file mode 100644
index 0000000..71bda8e
--- /dev/null
+++ b/doc/src/declarative/pics/edge2.png
Binary files differ
diff --git a/doc/src/declarative/pics/edge3.png b/doc/src/declarative/pics/edge3.png
new file mode 100644
index 0000000..51bb894
--- /dev/null
+++ b/doc/src/declarative/pics/edge3.png
Binary files differ
diff --git a/doc/src/declarative/pics/edge4.png b/doc/src/declarative/pics/edge4.png
new file mode 100644
index 0000000..aee3bd1
--- /dev/null
+++ b/doc/src/declarative/pics/edge4.png
Binary files differ
diff --git a/doc/src/declarative/pics/edges.png b/doc/src/declarative/pics/edges.png
new file mode 100644
index 0000000..211b101
--- /dev/null
+++ b/doc/src/declarative/pics/edges.png
Binary files differ
diff --git a/doc/src/declarative/pics/edges.svg b/doc/src/declarative/pics/edges.svg
new file mode 100644
index 0000000..25698ca
--- /dev/null
+++ b/doc/src/declarative/pics/edges.svg
@@ -0,0 +1,185 @@
+<?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://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"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser"
+ sodipodi:docname="edges.svg">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3850"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3856"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ </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="2.8583315"
+ inkscape:cx="372.04724"
+ inkscape:cy="596.15198"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1279"
+ inkscape:window-height="969"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <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:#0ca9fa;fill-opacity:1;stroke:black;stroke-width:0.04639034;stroke-miterlimit:4;stroke-dasharray:0.09278069, 0.04639034;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect1872"
+ width="33.656742"
+ height="39.808346"
+ x="208.86543"
+ y="390.22763"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 225.51888,380.99149 C 225.51888,439.06733 225.86873,439.06733 225.86873,439.06733"
+ id="path2760" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 242.97392,380.99149 C 242.97392,439.06733 243.32377,439.06733 243.32377,439.06733"
+ id="path3647" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 208.33832,380.99149 C 208.33832,439.06733 208.68817,439.06733 208.68817,439.06733"
+ id="path3649" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,409.67956 C 256.44329,409.67956 256.09344,409.67956 256.09344,409.67956"
+ id="path3651" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,429.97112 C 256.44329,429.97112 256.09344,429.97112 256.09344,429.97112"
+ id="path3653" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,390.78742 C 256.44329,390.78742 256.09344,390.78742 256.09344,390.78742"
+ id="path3655" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.54242"
+ y="393.58627"
+ id="text3657"><tspan
+ sodipodi:role="line"
+ id="tspan3659"
+ x="258.54242"
+ y="393.58627"
+ style="font-size:10px">Top</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.78955"
+ y="412.28455"
+ id="text3661"><tspan
+ sodipodi:role="line"
+ id="tspan3663"
+ x="258.78955"
+ y="412.28455"
+ style="font-size:10px">VerticalCenter</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="260.18896"
+ y="433.27582"
+ id="text3665"><tspan
+ sodipodi:role="line"
+ id="tspan3667"
+ x="260.18896"
+ y="433.27582"
+ style="font-size:10px">Bottom</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="198.96443"
+ y="376.24954"
+ id="text3669"><tspan
+ sodipodi:role="line"
+ id="tspan3671"
+ x="198.96443"
+ y="376.24954"
+ style="font-size:10px">Left</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="230.55408"
+ y="375.39383"
+ id="text3673"><tspan
+ sodipodi:role="line"
+ id="tspan3675"
+ x="230.55408"
+ y="375.39383"
+ style="font-size:10px">Right</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="186.71951"
+ y="355.25827"
+ id="text3677"><tspan
+ sodipodi:role="line"
+ id="tspan3679"
+ x="186.71951"
+ y="355.25827"
+ style="font-size:10px">HorizontalCenter</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Mstart)"
+ d="M 224.2567,375.39382 C 227.40539,356.85154 227.75525,357.20139 227.75525,357.20139"
+ id="path3681" />
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/edges_examples.svg b/doc/src/declarative/pics/edges_examples.svg
new file mode 100644
index 0000000..31e9901
--- /dev/null
+++ b/doc/src/declarative/pics/edges_examples.svg
@@ -0,0 +1,109 @@
+<?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://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"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg3885"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ inkscape:export-filename="/home/mbrasser/edge4.png"
+ inkscape:export-xdpi="189.65207"
+ inkscape:export-ydpi="189.65207"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="edges_examples.svg">
+ <defs
+ id="defs3887" />
+ <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="2"
+ inkscape:cx="162.62912"
+ inkscape:cy="591.92069"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="928"
+ inkscape:window-height="624"
+ inkscape:window-x="0"
+ inkscape:window-y="495" />
+ <metadata
+ id="metadata3890">
+ <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:#0ca9fa;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3893"
+ width="50"
+ height="50"
+ x="100"
+ y="414.36218" />
+ <rect
+ style="opacity:1;fill:#fa0c2a;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3895"
+ width="104"
+ height="50"
+ x="150"
+ y="414.36218" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="109"
+ y="443.65125"
+ id="text3897"><tspan
+ sodipodi:role="line"
+ id="tspan3899"
+ x="109"
+ y="443.65125">rect1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="186.54297"
+ y="443.65125"
+ id="text3901"><tspan
+ sodipodi:role="line"
+ id="tspan3903"
+ x="186.54297"
+ y="443.65125">rect2</tspan></text>
+ <rect
+ style="opacity:1;fill:#0ca9fa;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3905"
+ width="50"
+ height="50"
+ x="254"
+ y="414.36218" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="263"
+ y="443.65125"
+ id="text3907"><tspan
+ sodipodi:role="line"
+ id="tspan3909"
+ x="263"
+ y="443.65125">rect3</tspan></text>
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/edges_qml.png b/doc/src/declarative/pics/edges_qml.png
new file mode 100644
index 0000000..73f22f9
--- /dev/null
+++ b/doc/src/declarative/pics/edges_qml.png
Binary files differ
diff --git a/doc/src/declarative/pics/edges_qml.svg b/doc/src/declarative/pics/edges_qml.svg
new file mode 100644
index 0000000..1814ec6
--- /dev/null
+++ b/doc/src/declarative/pics/edges_qml.svg
@@ -0,0 +1,188 @@
+<?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://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"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="edges_qml.svg"
+ inkscape:export-filename="/home/mbrasser/edges_qml.png"
+ inkscape:export-xdpi="284.45999"
+ inkscape:export-ydpi="284.45999">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3850"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3856"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ </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="2.8583315"
+ inkscape:cx="372.04724"
+ inkscape:cy="596.15198"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1279"
+ inkscape:window-height="969"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <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:#0ca9fa;fill-opacity:1;stroke:black;stroke-width:0.04639034;stroke-miterlimit:4;stroke-dasharray:0.09278069, 0.04639034;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect1872"
+ width="33.656742"
+ height="39.808346"
+ x="208.86543"
+ y="390.22763"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 225.51888,380.99149 C 225.51888,439.06733 225.86873,439.06733 225.86873,439.06733"
+ id="path2760" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 242.97392,380.99149 C 242.97392,439.06733 243.32377,439.06733 243.32377,439.06733"
+ id="path3647" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 208.33832,380.99149 C 208.33832,439.06733 208.68817,439.06733 208.68817,439.06733"
+ id="path3649" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,409.67956 C 256.44329,409.67956 256.09344,409.67956 256.09344,409.67956"
+ id="path3651" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,429.97112 C 256.44329,429.97112 256.09344,429.97112 256.09344,429.97112"
+ id="path3653" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,390.78742 C 256.44329,390.78742 256.09344,390.78742 256.09344,390.78742"
+ id="path3655" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.54242"
+ y="393.58627"
+ id="text3657"><tspan
+ sodipodi:role="line"
+ id="tspan3659"
+ x="258.54242"
+ y="393.58627"
+ style="font-size:10px">top</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.78955"
+ y="412.28455"
+ id="text3661"><tspan
+ sodipodi:role="line"
+ id="tspan3663"
+ x="258.78955"
+ y="412.28455"
+ style="font-size:10px">verticalCenter</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="260.18896"
+ y="433.27582"
+ id="text3665"><tspan
+ sodipodi:role="line"
+ id="tspan3667"
+ x="260.18896"
+ y="433.27582"
+ style="font-size:10px">bottom</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="200.96443"
+ y="376.24954"
+ id="text3669"><tspan
+ sodipodi:role="line"
+ id="tspan3671"
+ x="200.96443"
+ y="376.24954"
+ style="font-size:10px">left</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="232.55408"
+ y="375.39383"
+ id="text3673"><tspan
+ sodipodi:role="line"
+ id="tspan3675"
+ x="232.55408"
+ y="375.39383"
+ style="font-size:10px">right</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="190.71951"
+ y="355.25827"
+ id="text3677"><tspan
+ sodipodi:role="line"
+ id="tspan3679"
+ x="190.71951"
+ y="355.25827"
+ style="font-size:10px">horizontalCenter</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-opacity:1"
+ d="M 226.2567,375.39382 C 229.40539,356.85154 229.75525,357.20139 229.75525,357.20139"
+ id="path3681" />
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/flickable.gif b/doc/src/declarative/pics/flickable.gif
new file mode 100644
index 0000000..f7a3319
--- /dev/null
+++ b/doc/src/declarative/pics/flickable.gif
Binary files differ
diff --git a/doc/src/declarative/pics/flipable.gif b/doc/src/declarative/pics/flipable.gif
new file mode 100644
index 0000000..6386f06
--- /dev/null
+++ b/doc/src/declarative/pics/flipable.gif
Binary files differ
diff --git a/doc/src/declarative/pics/gradient.png b/doc/src/declarative/pics/gradient.png
new file mode 100644
index 0000000..5eefdd2
--- /dev/null
+++ b/doc/src/declarative/pics/gradient.png
Binary files differ
diff --git a/doc/src/declarative/pics/gridLayout_example.png b/doc/src/declarative/pics/gridLayout_example.png
new file mode 100644
index 0000000..6b120e9
--- /dev/null
+++ b/doc/src/declarative/pics/gridLayout_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/gridview.png b/doc/src/declarative/pics/gridview.png
new file mode 100644
index 0000000..3726893
--- /dev/null
+++ b/doc/src/declarative/pics/gridview.png
Binary files differ
diff --git a/doc/src/declarative/pics/highlight.gif b/doc/src/declarative/pics/highlight.gif
new file mode 100644
index 0000000..fbef256
--- /dev/null
+++ b/doc/src/declarative/pics/highlight.gif
Binary files differ
diff --git a/doc/src/declarative/pics/horizontalLayout_example.png b/doc/src/declarative/pics/horizontalLayout_example.png
new file mode 100644
index 0000000..42f90ec
--- /dev/null
+++ b/doc/src/declarative/pics/horizontalLayout_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/layout-add.gif b/doc/src/declarative/pics/layout-add.gif
new file mode 100644
index 0000000..86e9247
--- /dev/null
+++ b/doc/src/declarative/pics/layout-add.gif
Binary files differ
diff --git a/doc/src/declarative/pics/layout-move.gif b/doc/src/declarative/pics/layout-move.gif
new file mode 100644
index 0000000..1825c22
--- /dev/null
+++ b/doc/src/declarative/pics/layout-move.gif
Binary files differ
diff --git a/doc/src/declarative/pics/layout-remove.gif b/doc/src/declarative/pics/layout-remove.gif
new file mode 100644
index 0000000..7086511
--- /dev/null
+++ b/doc/src/declarative/pics/layout-remove.gif
Binary files differ
diff --git a/doc/src/declarative/pics/margins_qml.png b/doc/src/declarative/pics/margins_qml.png
new file mode 100644
index 0000000..d7d73a3
--- /dev/null
+++ b/doc/src/declarative/pics/margins_qml.png
Binary files differ
diff --git a/doc/src/declarative/pics/margins_qml.svg b/doc/src/declarative/pics/margins_qml.svg
new file mode 100644
index 0000000..1f0ff02
--- /dev/null
+++ b/doc/src/declarative/pics/margins_qml.svg
@@ -0,0 +1,196 @@
+<?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://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"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="margins_qml.svg"
+ inkscape:export-filename="/home/mbrasser/edges_qml.png"
+ inkscape:export-xdpi="284.45999"
+ inkscape:export-ydpi="284.45999">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path2976"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path2979"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3850"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3856"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ </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="2.8583315"
+ inkscape:cx="372.04724"
+ inkscape:cy="596.15198"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1279"
+ inkscape:window-height="969"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <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:#0ca9fa;fill-opacity:1;stroke:black;stroke-width:0.04639034;stroke-miterlimit:4;stroke-dasharray:0.09278069, 0.04639034;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect1872"
+ width="33.656742"
+ height="39.808346"
+ x="208.86543"
+ y="390.22763"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02602077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02602088, 1.02602088;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 252.98692,377.00435 C 252.98692,443.05433 253.31077,443.05433 253.31077,443.05433"
+ id="path3647" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02601969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02602007, 1.02602007;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 198.35134,377.00433 C 198.35134,443.05431 198.67515,443.05431 198.67515,443.05431"
+ id="path3649" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02421367;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02421381, 1.02421381;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 193.94282,437.97112 C 257.43421,437.97112 257.06721,437.97112 257.06721,437.97112"
+ id="path3653" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02421367;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02421381, 1.02421381;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 193.94282,380.78742 C 257.43421,380.78742 257.06721,380.78742 257.06721,380.78742"
+ id="path3655" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="260.29169"
+ y="388.78741"
+ id="text1911"><tspan
+ sodipodi:role="line"
+ id="tspan1913"
+ x="260.29169"
+ y="388.78741"
+ style="font-size:10px">topMargin</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="259.65204"
+ y="437.27798"
+ id="text1915"><tspan
+ sodipodi:role="line"
+ id="tspan1917"
+ x="259.65204"
+ y="437.27798"
+ style="font-size:10px">bottomMargin</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="170.07939"
+ y="454.4209"
+ id="text1919"><tspan
+ sodipodi:role="line"
+ id="tspan1921"
+ x="170.07939"
+ y="454.4209"
+ style="font-size:10px">leftMargin</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="228.47504"
+ y="454.4209"
+ id="text1923"><tspan
+ sodipodi:role="line"
+ id="tspan1925"
+ x="228.47504"
+ y="454.4209"
+ style="font-size:10px">rightMargin</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.92020172px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 225.6938,382.51213 C 225.6938,388.91693 225.6938,388.91693 225.6938,388.91693"
+ id="path1929" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.92007709px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 225.6938,430.56703 C 225.6938,436.97192 225.6938,436.97192 225.6938,436.97192"
+ id="path3000" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-mid:none;marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 201.16631,410.1318 C 207.81355,410.1318 207.81355,410.1318 207.81355,410.1318"
+ id="path3002" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-mid:none;marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 244.02348,410.1318 C 250.67072,410.1318 250.67072,410.1318 250.67072,410.1318"
+ id="path3889" />
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/particles.gif b/doc/src/declarative/pics/particles.gif
new file mode 100644
index 0000000..763a8a8
--- /dev/null
+++ b/doc/src/declarative/pics/particles.gif
Binary files differ
diff --git a/doc/src/declarative/pics/pathview.gif b/doc/src/declarative/pics/pathview.gif
new file mode 100644
index 0000000..4052eb2
--- /dev/null
+++ b/doc/src/declarative/pics/pathview.gif
Binary files differ
diff --git a/doc/src/declarative/pics/propanim.gif b/doc/src/declarative/pics/propanim.gif
new file mode 100644
index 0000000..f86406e
--- /dev/null
+++ b/doc/src/declarative/pics/propanim.gif
Binary files differ
diff --git a/doc/src/declarative/pics/qtlogo.png b/doc/src/declarative/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/doc/src/declarative/pics/qtlogo.png
Binary files differ
diff --git a/doc/src/declarative/pics/reflection_example.png b/doc/src/declarative/pics/reflection_example.png
new file mode 100644
index 0000000..fd9bb48
--- /dev/null
+++ b/doc/src/declarative/pics/reflection_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/repeater.png b/doc/src/declarative/pics/repeater.png
new file mode 100644
index 0000000..973df27
--- /dev/null
+++ b/doc/src/declarative/pics/repeater.png
Binary files differ
diff --git a/doc/src/declarative/pics/scalegrid.svg b/doc/src/declarative/pics/scalegrid.svg
new file mode 100644
index 0000000..e386f3d
--- /dev/null
+++ b/doc/src/declarative/pics/scalegrid.svg
@@ -0,0 +1,183 @@
+<?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://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"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="scalegrid.svg"
+ inkscape:export-filename="/home/mbrasser/work/Kinetic/ngui/doc/src/pics/scalegrid.png"
+ inkscape:export-xdpi="189.65207"
+ inkscape:export-ydpi="189.65207">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="50"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="3.2163554"
+ inkscape:cx="173.89302"
+ inkscape:cy="703.69531"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:grid-bbox="false"
+ inkscape:guide-bbox="false"
+ inkscape:window-width="1409"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <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:red;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1876"
+ width="45.104"
+ height="45.137001"
+ x="119.16868"
+ y="301.00308"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.3965202;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304035, 0.39652018;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 157.02483,295.52571 C 157.02483,352.04784 157.02483,352.04784 157.02483,352.04784"
+ id="path2766" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.39652267;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304534, 0.39652268;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 126.2,295.64284 C 126.2,352.16567 126.2,352.16567 126.2,352.16567"
+ id="path2768" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.39652267;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304534, 0.39652268;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 169.05321,308.25967 C 112.53038,308.25967 112.53038,308.25967 112.53038,308.25967"
+ id="path2770" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.39652267;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304534, 0.39652268;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 169.08024,339.77238 C 112.55741,339.77238 112.55741,339.77238 112.55741,339.77238"
+ id="path2772" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
+ x="115.2857"
+ y="303.60583"
+ id="text2774"><tspan
+ sodipodi:role="line"
+ id="tspan2776"
+ x="115.2857"
+ y="303.60583">1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="137.19142"
+ y="303.60583"
+ id="text2782"><tspan
+ sodipodi:role="line"
+ id="tspan2784"
+ x="137.19142"
+ y="303.60583"
+ style="font-family:Arial Black">2</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
+ x="161.56842"
+ y="303.45935"
+ id="text2786"><tspan
+ sodipodi:role="line"
+ id="tspan2788"
+ x="161.56842"
+ y="303.45935">3</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="114.72613"
+ y="327.00702"
+ id="text2790"><tspan
+ sodipodi:role="line"
+ id="tspan2792"
+ x="114.72613"
+ y="327.00702"
+ style="font-family:Arial Black">4</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="137.12404"
+ y="326.86053"
+ id="text2794"><tspan
+ sodipodi:role="line"
+ id="tspan2796"
+ x="137.12404"
+ y="326.86053"
+ style="font-family:Arial Black">5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="161.49518"
+ y="326.86053"
+ id="text2798"><tspan
+ sodipodi:role="line"
+ id="tspan2800"
+ x="161.49518"
+ y="326.86053"
+ style="font-family:Arial Black">6</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="114.70855"
+ y="351.25809"
+ id="text2802"><tspan
+ sodipodi:role="line"
+ id="tspan2804"
+ x="114.70855"
+ y="351.25809"
+ style="font-family:Arial Black">7</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="137.08595"
+ y="351.1116"
+ id="text2806"><tspan
+ sodipodi:role="line"
+ id="tspan2808"
+ x="137.08595"
+ y="351.1116"
+ style="font-family:Arial Black">8</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="161.58307"
+ y="351.1116"
+ id="text2810"><tspan
+ sodipodi:role="line"
+ id="tspan2812"
+ x="161.58307"
+ y="351.1116"
+ style="font-family:Arial Black">9</tspan></text>
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/shadow_example.png b/doc/src/declarative/pics/shadow_example.png
new file mode 100644
index 0000000..6214620
--- /dev/null
+++ b/doc/src/declarative/pics/shadow_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/spacing_a.png b/doc/src/declarative/pics/spacing_a.png
new file mode 100644
index 0000000..ff07e2e
--- /dev/null
+++ b/doc/src/declarative/pics/spacing_a.png
Binary files differ
diff --git a/doc/src/declarative/pics/spacing_b.png b/doc/src/declarative/pics/spacing_b.png
new file mode 100644
index 0000000..94304ee
--- /dev/null
+++ b/doc/src/declarative/pics/spacing_b.png
Binary files differ
diff --git a/doc/src/declarative/pics/squish-transform.png b/doc/src/declarative/pics/squish-transform.png
new file mode 100644
index 0000000..0eb848e
--- /dev/null
+++ b/doc/src/declarative/pics/squish-transform.png
Binary files differ
diff --git a/doc/src/declarative/pics/squish.png b/doc/src/declarative/pics/squish.png
new file mode 100644
index 0000000..73bf292
--- /dev/null
+++ b/doc/src/declarative/pics/squish.png
Binary files differ
diff --git a/doc/src/declarative/pics/trivialListView.png b/doc/src/declarative/pics/trivialListView.png
new file mode 100644
index 0000000..3782570
--- /dev/null
+++ b/doc/src/declarative/pics/trivialListView.png
Binary files differ
diff --git a/doc/src/declarative/pics/verticalLayout_example.png b/doc/src/declarative/pics/verticalLayout_example.png
new file mode 100644
index 0000000..458dc7f
--- /dev/null
+++ b/doc/src/declarative/pics/verticalLayout_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/verticalLayout_transition.gif b/doc/src/declarative/pics/verticalLayout_transition.gif
new file mode 100644
index 0000000..ed61adb
--- /dev/null
+++ b/doc/src/declarative/pics/verticalLayout_transition.gif
Binary files differ
diff --git a/doc/src/declarative/pics/webview.png b/doc/src/declarative/pics/webview.png
new file mode 100644
index 0000000..0d24586
--- /dev/null
+++ b/doc/src/declarative/pics/webview.png
Binary files differ
diff --git a/doc/src/declarative/qmlforcpp.qdoc b/doc/src/declarative/qmlforcpp.qdoc
new file mode 100644
index 0000000..2898499
--- /dev/null
+++ b/doc/src/declarative/qmlforcpp.qdoc
@@ -0,0 +1,724 @@
+/*!
+ \page qmlforcpp.html
+ \target qmlforcpp
+ \title QML for C++ Programmers
+
+ This page describes the QML format and how to use and extend it from C++.
+
+ The QML syntax declaratively describes how to construct an in memory
+ object tree. QML is usually used to describe a visual scene graph
+ but it is not conceptually limited to this: the QML format is an abstract
+ description of \bold any object tree.
+
+ QML also includes property bindings. Bindings are ECMAScript expressions
+ of a properties value. Whenever the value of the expression changes -
+ either for the first time at startup or subsequently thereafter - the
+ property is automatically updated with the new value.
+
+ \section1 Loading and using QML Files
+
+ QmlComponent is used to load a QML file and to create object instances.
+
+ In QML a component is the unit of instantiation, and the most basic unit
+ of scope. A component is like a template for how to construct an object
+ tree. One component can create multiple instances of this tree, but the
+ template remains constant.
+
+ The following code uses the C++ interface to create 100 red rectangles
+ based on a simple declarative component description.
+
+ \code
+ QmlEngine engine;
+ QmlComponent redRectangle(&engine, "Rect { color: \"red\"; width: 100; height: 100 }");
+ for (int ii = 0; ii < 100; ++ii) {
+ QObject *rectangle = redRectangle.create();
+ // ... do something with the rectangle ...
+ }
+ \endcode
+
+ Each independent file describes a QML component, but it is also possible to
+ create sub-components within a QML file as will be shown later.
+
+ \section1 QML Format 101
+
+ This is some sample QML code.
+
+ \code
+ Image {
+ id: myRect
+ x: 10
+ y: 10
+ width: 100
+ height: 100
+ source: "background.png"
+
+ Text {
+ height: 50
+ width: 100
+ color: "white"
+ font.fontSize: 16
+ text: "Hello world!"
+ }
+ }
+ \endcode
+
+ The QML snippet shown above instantiates one \c Image instance and one
+ \c Text instance and sets properties on both. \bold Everything in QML
+ ultimately comes down to either instantiating an object instance, or
+ assigning a property a value. QML relies heavily on Qt's meta object system
+ and can only instantiate classes that derive from QObject.
+
+ In the above example, each property is placed on its own line. You can
+ also place multiple properties on one line by separating them with a
+ semi-colon. The code below is equivalent to the example above.
+
+ \code
+ Image {
+ id: myRect
+ x: 10; y: 10; width: 100; height: 100
+ source: "background.png"
+ Text { height: 50; width: 100; color: "white"; font.fontSize: 16; text: "Hello world!" }
+ }
+ \endcode
+
+ QML can set properties that are more complex than just simple types like
+ integers and strings. Properties can be object pointers or Qt interface
+ pointers or even lists of object or Qt interface pointers! QML is typesafe,
+ and will ensure that only the valid types are assigned to properties.
+
+ Assigning an object to a property is as simple as assigning a basic
+ integer. Attempting to assign an object to a property when type coercian
+ fails will produce an error. The following shows an example of valid and of
+ invalid QML and the corresponding C++ classes.
+
+ \table
+ \row \o
+ \code
+ class Image : public QObject
+ {
+ ...
+ Q_PROPERTY(ImageFilter *filter READ filter WRITE setFilter)
+ };
+
+ class ImageFilter : public QObject
+ {
+ ...
+ };
+ \endcode
+ \o \code
+ // OK
+ Image {
+ filter: ImageFilter {}
+ }
+
+ // NOT OK: Image cannot be cast into ImageFilter
+ Image {
+ filter: Image {}
+ }
+ \endcode
+ \endtable
+
+ Classes can also define an optional default property. The default property
+ is used for assignment if no explicit property has been specified.
+ Any object property can be the default, even complex properties like lists
+ of objects. The default property of the \c Rect class is the \c children
+ property, a list of \c Item's. In the following example, as both \c Image
+ and \c Text inherit from \c Item the \c Image and \c Text instances are
+ added to the parent's \c children property.
+
+ \code
+ Rect {
+ Image {}
+ Text {}
+ }
+ \endcode
+
+ Properties that return read-only object pointers can be used recursively.
+ This can be used, for example, to group properties together. The
+ \c Text element has a \c font property that returns an object with a number
+ of sub-properties such as \c family, \c bold, \c italic and \c size.
+ QML makes it easy to interact with these grouped properties, as the
+ following shows - everything you would expect to work, just does.
+
+ \table
+ \row \o
+ \code
+ class Text : public ...
+ {
+ ...
+ Q_PROPERTY(Font *font READ font);
+ };
+ class Font : public QObject
+ {
+ ...
+ Q_PROPERTY(QString family READ family WRITE setFamily);
+ Q_PROPERTY(bool bold READ bold WRITE setBold);
+ Q_PROPERTY(bool italic READ italic WRITE setItalic);
+ Q_PROPERTY(int size READ size WRITE setSize);
+ };
+ \endcode
+ \o
+ \code
+ Text {
+ font.family: "helvetica"
+ font.size: 12
+ font {
+ bold: true
+ italic: true
+ }
+ }
+ \endcode
+ \endtable
+
+ \section1 Defining QML Types
+
+ The QML engine has no intrinsic knowledge of any class types. Instead
+ the programmer must define the C++ types, and their corresponding QML
+ name.
+
+ \code
+ #define QML_DECLARE_TYPE(T)
+ #define QML_DEFINE_TYPE(T,QmlName)
+ \endcode
+
+ Adding these macros to your library or executable automatically makes the
+ C++ type \a T available from the declarative markup language under the
+ name \a QmlName. Of course there's nothing stopping you using the same
+ name for both the C++ and the QML name!
+ Any type can be added to the QML engine using these macros. The only
+ requirements are that \a T inherits QObject and that it has a default constructor.
+
+ \section1 Property Binding
+
+ Assigning constant values and trees to properties will only get you so
+ far. Property binding allows a property's value to be dependant on the
+ value of other properties and data. Whenever these dependencies change,
+ the property's value is automatically updated.
+
+ Property bindings are ECMAScript expressions and can be applied to any
+ object property. C++ classes don't have to do anything special to get
+ binding support other than define appropriate properties. When a non-literal
+ property assignment appears in a QML file, it is automatically treated as a
+ property binding.
+
+ Here's a simple example that stacks a red, blue and green rectangle.
+ Bindings are used to ensure that the height of each is kept equal to it's
+ parent's. Were the root rectangle's height property to change, the child
+ rectangles height would be updated automatically.
+
+ \code
+ Rect {
+ color: "red"
+ width: 100
+ Rect {
+ color: "blue"
+ width: 50
+ height: parent.height
+ Rect {
+ color: "green"
+ width: 25
+ height: parent.height
+ }
+ }
+ }
+ \endcode
+
+ Binding expressions execute in a context. A context behaves as a scope and
+ defines how the expression resolves property and variable names. Although
+ the two expressions in the last example are the same, the value of \c parent
+ resolves differently because each executes in a different context. Although
+ QML generally takes care of everything for the programmer, a thorough
+ understanding of bind contexts is important in some of the more complex QML
+ structures.
+
+ Every expression is executed in a bind context, encapsulated by the
+ QmlBindContext C++ class. As covered in the class documentation, a
+ bind context contains a map of names to values, and a list of default
+ objects. When resolving a name, the name to value map is searched first.
+ If the name cannot be found, the default object's are iterated in turn and
+ the context attempts to resolve the name as a property of one of the default
+ objects.
+
+ There are generally two contexts involved in the execution of a binding.
+ The first is the "object context" - a bind context associated with the
+ closest instantiated object and containing just one default object, and
+ that's instantiated object itself. The effect of the object
+ context is pretty simple - names in the binding expression resolve to
+ properties on the object first. It is important to note - particularly in
+ the case of grouped properties - the object context is that of the
+ instantiated object, the consequences of which are shown below.
+
+ \code
+ // OK // NOT OK
+ Text { Text {
+ font { font {
+ bold: font.italic bold: italic
+ } }
+ } }
+ \endcode
+
+ The second context is the "component context". Each QML component (and
+ consequently each QML file) is created in its own unique binding context.
+ Like the object context, the component context contains just one default
+ object - but in this case it is the component's root object. An example
+ will illustrate best - the resultant text will read "background.png".
+
+ \code
+ Image {
+ source: "background.png"
+ Text {
+ text: source
+ }
+ }
+ \endcode
+
+ If the name is not found in either of these contexts, the context heirarchy
+ is searched parent-by-parent until the name is either found, or the
+ heirarchy is exhausted.
+
+ The first property binding example shown involved fixing the height of three
+ rectangles. It did this by fixing the height of each rectangle to its
+ parent, rather than fixing them all to a single common point. Here's the
+ example rewritten to do just that.
+
+ \code
+ Rect {
+ color: "red"
+ width: 100
+ Rect {
+ color: "blue"
+ width: 50
+ height: parent.height
+ Rect {
+ color: "green"
+ width: 25
+ height: parent.parent.height
+ }
+ }
+ }
+ \endcode
+
+ Clearly this sort of fragile relationship is undesirable and unmanageable -
+ moving the green rectangle to be a sibling of the blue or introducing a
+ further rectangle between the two would break the example.
+
+ To address this problem, QML includes a way to directly reference any object
+ within a component (or parent component for that matter), called "ids".
+ Developers assign an object an id, and can then reference it directly by
+ name. Developers assign an object an id by setting the special \c id
+ property. Every object automatically has this magical property (if the
+ object also has an actual property called \c id, that gets set too). As
+ an id allows an object to be referenced directly, it must be unique within
+ a component. By convention, id's should start with an uppercase letter.
+
+ \code
+ Rect {
+ id: Root
+ color: "red"
+ width: GreenRect.width + 75
+ height: Root.height
+ Rect {
+ color: "blue"
+ width: GreenRect.width + 25
+ Rect {
+ id: GreenRect
+ color: "green"
+ width: 25
+ height: Root.height
+ }
+ }
+ }
+ \endcode
+
+ To relate id's back to QmlBindContext, id's exist as properties on the
+ component context.
+
+ Bind expressions can reference any object property. The QML bind engine
+ relies on the presence of the NOTIFY signal in the Q_PROPERTY declaration
+ on a class to alert it that a property's value has changed. If this is
+ omitted, the bind expression can still access the property's value, but
+ the expression will not be updated if the value changes. The following is
+ an example of a QML friendly property declaration.
+
+ \code
+ class Example : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY(int sample READ sample WRITE setSample NOTIFY sampleChanged)
+ public:
+ int sample() const;
+ void setSample(int);
+ signals:
+ void sampleChanged(int);
+ };
+ \endcode
+
+ While generally no changes are needed to a C++ class to use property
+ binding, sometimes more advanced interaction between the binding engine and
+ an object is desirable. To facilitate this, there is a special exception
+ in the bind engine for allowing an object to access the binding directly.
+
+ If a binding is assigned to a property with a type of QmlBindableValue
+ pointer (ie. QmlBindableValue *), each time the binding value changes,
+ a QmlBindableValue instance is assigned to that property. The
+ QmlBindableValue instance allows the object to read the binding and to
+ evaluate the binding's current value.
+
+ \section1 Signal Properties
+
+ In addition to reading and writing regular properties, QML allows you to
+ easily associate ECMAScript with signals. Consider the following example,
+ in which Button is a made-up type with a clicked() signal.
+
+ \code
+ Button {
+ text: "Hello world!"
+ onClicked: print(text)
+ }
+ \endcode
+
+ Clicking on the button causes "Hello world!" to be printed to the console
+ (or lost forever if you're running Windows).
+
+ Like properties, signals automatically become available in QML without
+ any additional work. As illustrated signals are mapped into QML as special
+ "signal properties", using the name "on<Signal Name>" where the first
+ character of the signal's name is uppercased. If more than one signal of
+ the same name is exist on a class, only the first is available (see the
+ \l Connection element for more general signal connections).
+
+ An important observation to make here is the lack of braces. While both
+ property bindings and signal properties involve executing ECMAScript code,
+ property bindings dynamically update the property value (hence the braces),
+ whereas with signal properties the constant script "value" is actually
+ assigned to the signal property. Trying to bind a value to a signal
+ property will not work!
+
+ Signal parameters are also available to the executing script, as shown
+ below, as long as you remember to name the parameters of your signal
+ in C++ (see QMetaMethod::parameterNames()).
+
+ \table
+ \row \o
+ \code
+ Example {
+ onDoSomething: for(var ii = 0; ii &lt; count; ++ii)
+ print(message)
+ }
+ \endcode
+ \o
+ \code
+ class Example : public QObject
+ {
+ Q_OBJECT
+ signals:
+ void doSomething(int count, const QString &message);
+ };
+ \endcode
+ \endtable
+
+ Just like property bindings, signal scripts are executed in a context. The
+ signal script context is identical in scope to the "object context" under
+ property binding, with the exception that it has the signal parameters
+ bound in.
+
+ In addition to scripts, it is possible to assign objects to signal properties.
+ This automatically connects the signal to the object's default method. A
+ default method is defined just like a default property, though the special
+ "DefaultMethod" class info.
+
+ \code
+ Q_CLASSINFO("DefaultMethod", "myMethod(int)");
+ \endcode
+
+ This is useful in achieving several use cases, like that below which moves
+ the button when it is clicked.
+
+ \code
+ Button {
+ id: MyButton
+ onClicked: NumericAnimation {
+ target: MyButton
+ property: "x"
+ to: 100
+ }
+ }
+ \endcode
+
+ If the class itself actually defines a property called "on<Name>", this will
+ be assigned the string value and the signal handling behaviour will be
+ disabled.
+
+ \section1 Attached Properties
+
+ Attached properties allow unrelated types to annotate another type with some
+ additional properties. Some APIs or operations are inherintly imperative,
+ and attached properties help out when translating these APIs into the
+ declarative QML language.
+
+ Qt's QGridLayout is one such example.
+
+ \code
+ QGridLayout {
+ QLabel {
+ QGridLayout.row: 0
+ QGridLayout.column: 0
+ text: "Name:"
+ }
+ QLineEdit {
+ QGridLayout.row: 0
+ QGridLayout.column: 1
+ }
+
+ QLabel {
+ QGridLayout.row: 1
+ QGridLayout.column: 0
+ text: "Occupation:"
+ }
+ QLineEdit {
+ QGridLayout.row: 1
+ QGridLayout.column: 1
+ }
+ }
+ \endcode
+
+ Attached properties are identified by the use of a type name, in the
+ case shown \c QGridLayout, as a grouped property specifier. To prevent
+ ambiguity with actual class instantiations, attached properties must
+ always be specified to include a period but can otherwise be used just like
+ regular properties.
+
+ C++ types provide attached properties by declaring the public function \c qmlAttachedProperties like this example.
+
+ \table
+ \row \o
+ \code
+ static QObject *Type::qmlAttachedProperties(QObject *);
+ \endcode
+ \o
+ \code
+ class Example : public QObject
+ {
+ Q_OBJECT
+ public:
+ static QObject *qmlAttachedProperties(QObject *);
+ };
+ \endcode
+ \endtable
+
+ When an attached property is accessed, the QML engine will call this method
+ to create an attachment object, passing in the object instance that the
+ attached property applies to. The attachment object should define all
+ the attached properties, and is generally parented to the provided object
+ instance to avoid memory leaks. The QML engine does not saves this object,
+ so it is not necessary for the attached property function to ensure that
+ multiple calls for the same instance object return the same attached object.
+
+ While conceptually simple, implementing an attachment object is not quite
+ so easy. The \c qmlAttachedProperties function is static - attachment
+ objects are not associated with any particular instance. How the values
+ of the attached properties apply to the behaviour they are controlling is
+ entirely implementation dependent. An additional consequence of this is
+ that \bold any object can attach \bold any attached property. The following is
+ perfectly valid, although the attached property has no actual effect:
+
+ \code
+ FancyGridLayout {
+ Item {
+ Button {
+ QGridLayout.row: 1
+ }
+ }
+ }
+ \endcode
+
+ The property has no effect because the (made-up) FancyGridLayout type defines the meaning
+ of the \c row attached property only to apply to its direct children. It
+ is possible that other types may have attached properties that affect
+ objects that aren't their direct children.
+
+ Attached properties are an advanced feature that should be used with
+ caution.
+
+ \note We may implement a convenience wrapper that makes using attached
+ properties easier for the common "attach to children" case.
+
+ \section1 Property Value Sources
+
+ Intrinsically, the QML engine can assign a property either a static value,
+ such as a number or an object tree, or a property binding. It is possible for
+ advanced users to extend the engine to assign other "types" of values to
+ properties. These "types" are known as property value sources.
+
+ Consider the following example.
+
+ \code
+ Rect {
+ x: NumericAnimation { running: true; repeat; true; from: 0; to: 100; }
+ }
+ \endcode
+
+ Here the \c x property of the rectangle will be animated from 0 to 100.
+ To support this, the NumericAnimation class inherits the
+ QmlPropertyValueSource class. If a type inherits this class and is assigned
+ to a property for which type assignment would otherwise fail (ie. the
+ property itself doesn't have a type of QmlPropertyValueSource *), the QML
+ engine will automatically set the property as the target of the value
+ source.
+
+ \section1 Extending types in QML
+
+ QML is designed to allow you to build fully working types without writing
+ a line of C++ code. This is, for example, used extensively when designing
+ applications using the Fluid UI primitives. To create new types, it is
+ necessary to be able to define new signals, slots and properties in QML.
+
+ In this example, a Button is extended to have an additional
+ "text2" property (which always returns "Hello world!") and an additional
+ signal "clicked2" that is also emitted when the button is clicked. Not
+ a very useful extension, but an extension nonetheless.
+
+ \table
+ \row
+ \o
+ \code
+ QmlEngine engine;
+ QmlComponent component(&engine, qmlData);
+ QObject *object = component.create();
+ // Will print "Hello world!"
+ qDebug() << object->property("text2");
+ // Will be emitted whenever the button is clicked
+ QObject::connect(object, SIGNAL(clicked2()), this, SLOT(...));
+ \endcode
+ \o
+ \code
+ Button {
+ property string text2
+ signal clicked2
+
+ text: "Hello!"
+ text2: "Hello world!"
+ onClicked: clicked2.emit()
+ }
+ \endcode
+ \endtable
+
+ The general syntax for defining new properties and signals is:
+
+ \list
+ \o
+ \code
+ [default] property <type> <name> [: <default value>]
+ \endcode
+
+ Where type can be one of \e int, \e bool, \e double, \e real, \e string,
+ \e color, \e date, \e var or \e variant.
+
+ \o
+ \code
+ signal <name>
+ \endcode
+ Currently only parameterless signals are supported.
+ \endlist
+
+ \section1 Parser Status
+
+ Generally using QML is a breeze - you implement your classes in C++, add
+ the appropriate properties, signals and slots and off you go. The QML
+ engine takes care of instantiating your classes and setting the properties
+ and everything works fine.
+
+ However, sometimes it is helpful to know a little more about the status of
+ the QML parser. For example, it might be beneficial from a performance
+ standpoint to delay initializing some data structures until all the
+ properties have been set.
+
+ To assist with this, the QML engine defines an interface class called
+ QmlParserStatus. The interface defines a number of virtual methods that are
+ invoked at various stages of the component instantiation. To receive
+ these notifications, all a class has to do is to inherit the interface, and
+ notify the Qt meta system using the Q_INTERFACES() macro. For example,
+
+ \code
+ class Example : public QObject, public QmlParserStatus
+ {
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+ public:
+ virtual void componentComplete()
+ {
+ qDebug() << "Woohoo! Now to do my costly initialization";
+ }
+ };
+ \endcode
+
+ \section1 Extended Type Definitions
+
+ QML requires that types have the appropriate properties and signals to
+ work well within the declarative environment. In the case of existing
+ types, it is sometimes necessary to add signals, properties or slots to a
+ target class to make it more QML friendly but the original type cannot be
+ modified. For these cases, the QML engine supports extended type
+ definitions.
+
+ An extended type definition allows the programmer to supply an additional
+ type - known as the extension type - when registering the target class
+ whose properties, signals and slots are transparently merged with the
+ original target class when used from within QML.
+
+ An extension class is a regular QObject, with a constructor that takes a
+ QObject pointer. When needed (extension classes are delay created
+ until the first extension attribute is accessed) the extension
+ class is created and the target object is passed in as the parent. When
+ an extension attribute on the original is accessed, the appropriate signal,
+ property or slots on the extension object is used instead.
+
+ When an extended type is installed, the
+ \code
+ #define QML_DEFINE_EXTENDED_TYPE(T,QmlName,ExtendedTypeName)
+ \endcode
+ macro should be used instead of the regular \c QML_DEFINE_TYPE.
+
+ This example shows the addition of a read-only \c textLength property to
+ QLabel being implemented as an extension.
+
+ \table
+ \row
+ \o
+ \code
+ class QLabelExtension : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY(int textLength READ textLength)
+ public:
+ QWidgetExtension(QObject *parent) : QObject(parent) {}
+ int textLength() const {
+ return static_cast<QLabel *>(parent())->text().count();
+ }
+ };
+ QML_DEFINE_EXTENDED_TYPE(QLabel,QLabel,QLabelExtension);
+ \endcode
+ \o
+ \code
+ QLabel {
+ id: Label1
+ text: "Hello World!"
+ }
+ QLabel {
+ text: "Label1 text length: " + Label1.textLength
+ }
+ \endcode
+ \endtable
+
+ Attributes defined through extensions are inherited, just like attributes
+ defined on a normal class. Any types that inherit from \c QLabel, will
+ also have the \c textLength property. Derived types can include additional
+ extensions which are merged together, but only a single extension can be
+ specified for each single C++ class.
+
+ Extended type definitions can even be used to add an attached properties
+ function to a type - just declare the \c qmlAttachedProperties function on
+ the extension object.
+
+*/
+
diff --git a/doc/src/declarative/qmlintro.qdoc b/doc/src/declarative/qmlintro.qdoc
new file mode 100644
index 0000000..c507e75
--- /dev/null
+++ b/doc/src/declarative/qmlintro.qdoc
@@ -0,0 +1,226 @@
+/*!
+\page qmlintroduction.html
+\title Introduction to the Qml language
+
+\tableofcontents
+
+\section1 What is Qml?
+
+Qml is a declarative language designed to describe the user interface of a
+program: both what it looks like and how it behaves. In Qml, a user
+interface is specified as a tree of objects with properties.
+
+\section1 What should I know before starting?
+
+This introduction is meant for those with little or no programming
+experience. JavaScript is used as a scripting language in Qml, so you may want
+to learn a bit more about it (\l{JavaScript: The Definitive Guide}) before diving
+too deep into Qml. It's also helpful to have a basic understanding of other web
+technologies like HTML and CSS, but not required.
+
+\section1 Basic Qml Syntax
+
+Qml looks like this:
+
+\code
+Rect {
+ width: 200
+ height: 200
+ color: "white"
+ Image {
+ source: "pics/logo.png"
+ anchors.centeredIn: parent
+ }
+}
+\endcode
+
+Objects are specified by their type, followed by a pair of braces. Object
+types always begin with a capital letter. In the above example, there are
+two objects, a \l Rect, and an \l Image. Between the braces, we can specify
+information about the object, such as its properties.
+
+Properties are specified as \c {property: value} (much like CSS). In the above
+example, we can see the Image has a property named \e source, which has been
+assigned the value \e "pics/logo.png". The property and its value are
+separated by a colon.
+
+Properties can be specified one-per-line:
+
+\code
+Rect {
+ width: 100
+ height: 100
+}
+\endcode
+
+or you can put multiple properties on a single line:
+
+\code
+Rect { width: 100; height: 100 }
+\endcode
+
+When multiple property/value pairs are specified on a single line, they
+must be separated by a semicolon.
+
+\section1 Expressions
+
+In addition to assigning values to properties, you can also assign
+expressions written in JavaScript.
+
+\code
+Rotation { angle: 360*3 }
+\endcode
+
+These expressions can include references to other objects and properties, in which case
+a \e binding is established: when the value of the expression changes, the property the
+expression has been assigned to is automatically updated to that value.
+
+\code
+Item {
+ Text {
+ id: Text1
+ text: "Hello World"
+ }
+ Text {
+ id: Text2
+ text: Text1.text
+ }
+}
+\endcode
+
+In the example above, the Text2 object will display the same text as Text1. If Text1 is updated,
+Text2 will be updated as well.
+
+Note that to refer to other objects, we use their \e id (more information on the id property can be
+found in a following section).
+
+\section1 Qml Comments
+
+Commenting in Qml is similar to JavaScript.
+\list
+\o Single line comments begin with // and end at the end of the line.
+\o Multiline comments begin with /* and end with *\/
+\endlist
+
+\quotefile doc/src/snippets/declarative/comments.qml
+
+Comments are ignored by the engine. The are useful for explaining what you
+are doing: for referring back to at a later date, or for others reading
+your Qml files.
+
+Comments can also be used to prevent the execution of code, which is
+sometimes useful for tracking down problems.
+
+\code
+Text {
+ text: "Hello world!"
+ //opacity: 0.5
+}
+\endcode
+
+In the above example, the Text object will have normal opacity, since the
+line opacity: 0.5 has been turned into a comment.
+
+\section1 Properties
+
+\section2 Property naming
+
+Properties begin with a lowercase letter (with the exception of \l{Attached Properties}).
+
+\section2 Property types
+
+Qml supports properties of many types (\l{Common QML Types}). The basic types include int,
+real, bool, string, color, and lists.
+
+\code
+Item {
+ x: 10.5 // a 'real' property
+ ...
+ state: "Details" // a 'string' property
+ focus: true // a 'bool' property
+}
+\endcode
+
+Qml properties are what is known as \e typesafe. That is, they only allow you to assign a value that
+matches the property type. For example, the scale property of item is a real, and if you try to assign
+a string to it you will get an error.
+
+\badcode
+Item {
+ scale: "hello" //illegal!
+}
+\endcode
+
+\section3 The 'id' property
+
+The id property is a special property of type \e id. Assigning an id to an object allows you
+to refer to it elsewhere.
+
+\code
+Item {
+ Text {
+ id: MyName
+ text: "..."
+ }
+ Text {
+ text: MyName.text
+ }
+}
+\endcode
+
+ids must begin with a letter. We recommended that you start your ids with a capital letter.
+
+\section2 List properties
+
+List properties look like this:
+
+\code
+Item {
+ children: [
+ Image {},
+ Text {}
+ ]
+}
+\endcode
+
+The list is enclosed in square brackets, with a comma separating the
+list elements. In cases where you are only assigning a single item to a
+list, you can omit the square brackets:
+
+\code
+Image {
+ children: Rect {}
+}
+\endcode
+
+\section2 Default properties
+
+Each object type can specify one of it's list properties as its default property.
+If a list property has been the default property, it means the property tag can emitted:
+
+\code
+State {
+ operations: [
+ SetProperties {},
+ SetProperties {}
+ ]
+}
+\endcode
+
+can be simplified to
+
+\code
+State {
+ SetProperties {}
+ SetProperties {}
+}
+\endcode
+
+\section2 Dot Properties
+
+\section2 Attached Properties
+\target attached-properties
+
+\section2 Signal Handlers
+
+*/
diff --git a/doc/src/declarative/qmlreference.qdoc b/doc/src/declarative/qmlreference.qdoc
new file mode 100644
index 0000000..cbd086c
--- /dev/null
+++ b/doc/src/declarative/qmlreference.qdoc
@@ -0,0 +1,42 @@
+/*!
+ \page qmlreference.html
+ \title Qml Reference
+
+ \target qtdeclarativemainpage
+
+ QML is a language for building highly dynamic and fluid applications. It is targetted at the sorts of user
+ interface (and the sorts of hardware) in embedded devices such as phones, media
+ players, and set-top boxes. It is also appropriate for highly custom desktop
+ user-interfaces, or special elements in more traditional desktop
+ user-interfaces.
+
+ Building fluid applications is done declaratively, rather than procedurally.
+ That is, you specify \e what the UI should look like and how it should behave
+ rather than specifying step-by-step \e how to build it. Specifying a UI declaratively
+ does not just include the layout of the interface items, but also the way each
+ individual item looks and behaves and the overall flow of the application.
+
+ Getting Started:
+ \list
+ \o \l {qmlexamples}{Examples}
+ \o \l {tutorial}{Tutorial: 'Hello World'}
+ \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'}
+ \o \l {Introduction to the Qml language} (in progress)
+ \endlist
+
+ Core Features:
+ \list
+ \o \l {binding}{Data Binding}
+ \o \l {anchor-layout}{Layout Anchors}
+ \o \l {qmlanimation}{Animation}
+ \o \l {qmleffects}{Visual Effects}
+ \o \l {components}{Components}
+ \o \l {qmlmodules}{Modules}
+ \o \l {qmlfocus}{Keyboard Focus}
+ \endlist
+
+ QML Reference:
+ \list
+ \o \l {elements}{Qml Elements}
+ \endlist
+*/
diff --git a/doc/src/declarative/qmlviewer.qdoc b/doc/src/declarative/qmlviewer.qdoc
new file mode 100644
index 0000000..8228737
--- /dev/null
+++ b/doc/src/declarative/qmlviewer.qdoc
@@ -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 documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qmlviewer.html
+ \title Qt Declarative UI Viewer (qmlviewer)
+ \ingroup qttools
+ \keyword qmlviewer
+
+ This page documents the \e{Declarative UI Viewer} for the Qt GUI
+ toolkit. The \c qmlviewer reads a declarative user interface definition
+ (\c .qml) file and displays the user interface it describes.
+
+ \section1 Options
+
+ When run with the \c -help option, qmlviewer shows available options.
+
+ \section1 Dummy Data
+
+ One use of qmlviewer is to allow QML files to be viewed stand-alone,
+ rather than being loaded from within a Qt program. Qt applications will
+ usually bind objects and properties into the execution context before
+ running the QML. To stand-in for such bindings, you can provide dummy
+ data: create a directory called "dummydata" in the same directory as
+ the target QML file and create files there with the "qml" extension.
+ All such files will be loaded as QML objects and bound to the root
+ context as a property with the name of the file (without ".qml").
+
+ For example, if the Qt application has a "clock.time" property
+ that is a qreal from 0 to 86400 representing the number of seconds since
+ midnight, dummy data for this could be provided by \c dummydata/clock.qml:
+ \code
+ Object { property real time: 12345 }
+ \endcode
+ Any QML can be used in the dummy data files. You could even animate the
+ fictional data!
+*/
diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc
new file mode 100644
index 0000000..4fe9994
--- /dev/null
+++ b/doc/src/declarative/qtdeclarative.qdoc
@@ -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 documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \module QtDeclarative
+ \title QtDeclarative Module
+ \ingroup modules
+
+ \brief The Qt Declarative module provides a declarative framework for building
+ highly dynamic and fluid applications.
+
+ Qt Declarative is targetted at the sorts of user
+ interface (and the sorts of hardware) in embedded devices such as phones, media
+ players, and set-top boxes. It is also appropriate for highly custom desktop
+ user-interfaces, or special elements in more traditional desktop
+ user-interfaces.
+
+ Building fluid applications is done declaratively, rather than procedurally.
+ That is, you specify \e what the UI should look like and how it should behave
+ in an declarative format called QML, rather than specifying step-by-step \e how to
+ build it in a language like C++ or JavaScript. Specifying a UI declaratively
+ does not just include the layout of the interface items, but also the way each
+ individual item looks and behaves and the overall flow of the application.
+
+ Getting Started:
+ \list
+ \o \l {qmlexamples}{Examples}
+ \o \l {tutorial}{Tutorial: 'Hello World'}
+ \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'}
+ \o \l {qmlforcpp}{QML For C++ Programmers}
+ \endlist
+
+ Core Features:
+ \list
+ \o \l {binding}{Data Binding}
+ \o \l {anchor-layout}{Layout Anchors}
+ \o \l {qmlanimation}{Animation}
+ \o \l {qmleffects}{Visual Effects}
+ \o \l {components}{Components}
+ \o \l {qmlmodules}{Modules}
+ \o \l {qmlfocus}{Keyboard Focus}
+ \endlist
+
+ QML Reference:
+ \list
+ \o \l {elements}{Qml Elements}
+ \endlist
+
+ C++ Reference:
+ \list
+ \o \l {qtbinding}{C++ Data Binding}
+ \o \l {cppitem}{C++ Components}
+ \endlist
+*/
diff --git a/doc/src/declarative/qtprogrammers.qdoc b/doc/src/declarative/qtprogrammers.qdoc
new file mode 100644
index 0000000..6777724
--- /dev/null
+++ b/doc/src/declarative/qtprogrammers.qdoc
@@ -0,0 +1,124 @@
+/*
+
+ INCOMPLETE
+
+\page qtprogrammers.html
+\target qtprogrammers
+\title QML for Qt programmers
+
+\section1 Overview
+
+While QML does not require Qt knowledge to use, if you \e are already familar with Qt,
+much of your knowledge is directly relevant to learning and using QML. Of course,
+an application with a UI defined in QML also uses Qt for all the non-UI logic.
+
+\section1 Familiar Concepts
+
+QML provides direct access to the following concepts from Qt:
+
+\list
+ \o QAction - the \l {basicqmlaction}{action} type
+ \o QObject signals and slots - available as functions to call in JavaScript
+ \o QObject properties - available as variables in JavaScript
+ \o QWidget - QFxView is a QML-displaying widget
+ \o Qt models - used directly in data binding (QAbstractItemModel and next generation QListModelInterface)
+\endlist
+
+Qt knowledge is \e required for \l {cppitem}{writing elements in C++}.
+
+
+\section1 QML Items compared with QWidgets
+
+QML Items are very similar to QWidgets: they define the look and feel of the user interface. (Note that while QWidgets
+haven't traditionally been used to define the look and feel of view delegates, QML Items can be used for this as well.)
+
+There are three structurally different types of QWidget:
+
+\list
+ \o Simple widgets that are not used as parents (QLabel, QCheckBox, QToolButton, etc.)
+ \o Parent widgets that are normally used as parents to other widgets (QGroupBox, QStackedWidget, QTabWidget, etc.)
+ \o Compound widgets that are internally composed of child widgets (QComboBox, QSpinBox, QFileDialog, QTabWidget, etc.)
+\endlist
+
+QML Items also serve these purposes. Each is considered separately below.
+
+\section2 Simple Widgets
+
+The most important rule to remember while implementing a new QFxItem in C++
+is that it should not contain any look and feel policies - leave that to the
+QML usage of the item.
+
+As an example, imagine you wanted a reusable Button item. If you therefore
+decided to write a QFxItem subclass to implement a button,
+just as QToolButton subclasses QWidget for this purpose, following the rule above, your
+"QFxButton" would not have any appearance - just the notions of enabled, triggering, etc.
+
+But there is already an object in Qt that does this: QAction.
+
+QAction is the UI-agnostic essence of QPushButton, QCheckBox, QMenu items, QToolButton,
+and other visual widgets that are commonly bound to a QAction.
+
+So, the job of implementing a checkbox abstraction for QML is already done - it's QAction.
+The look and feel of an action - the appearance of the button, the transition between states,
+and exactly how it respond to mouse, key, or touch input, should all be left for definition
+in QML.
+
+It is illustrative to note that QFxTextEdit is built upon QTextControl,
+QFxWebView is built upon QWebPage, and ListView uses QListModelInterface,
+just as QTextEdit, QWebView, and QListView are built upon
+those same UI-agnostic components.
+
+The encapsulation of the look and feel that QWidgets gives is important, and for this
+the QML concept of \l components serves the same purpose. If you are building a complete
+suite of applications which should have a consistent look and feel, you should build
+a set of reusable components with the look and feel you desire.
+
+So, to implement your reusable button, you would simply build a QML component.
+
+
+\section2 Parent Widgets
+
+Parent widgets each provide a generic way to interface to one or more arbitrary other widgets.
+A QTabWidget provides an interface to multiple "pages", one of which is visible at any time,
+and a mechnism for selecting among them (the QTabBar). A QScollArea provides scrollbars around
+a widget that is otherwise too large to fit in available space.
+
+Nearly all such components can be created directly in QML. Only a few cases
+which require very particular event handling, such as Flickable, require C++ implementations.
+
+As an example, imagine you decided to make a generic tab widget item to be used
+through your application suite wherever information is in such quantity that it
+needs to be divided up into pages.
+
+To do this in QML, ... \todo example of container definition.
+
+A significant difference in the parenting concept with QML compare to QWidgets
+is that while child items are positioned relative to their parents,
+there is no requirement that they be wholy contained ("clipped") to
+the parent (although the clipped property of the child Item does allow
+this where it is needed).
+This difference has rather far-reaching consequences, for example:
+
+\list
+ \o A shadow or highlight around a widget could be a child of that widget.
+ \o Particle effects can flow outside the object where they originate.
+ \o Transitioning animations can "hide" items by visibly moving them beyond the screen bounds.
+\endlist
+
+
+\section2 Compound Widgets
+
+Some widgets provide functionality by composing other widgets as an "implementation detail",
+providing a higher level API to the composition. QSpinBox for example is a line edit and some
+buttons to increase/decrease the edited value. QFileDialog uses a whole host of widgets to
+give the user a way of finding and selecting a file name.
+
+When developing reusable QML Items, you may choose to do the same: build an item composed
+of other items you have already defined.
+
+The only caveat when doing this is to consider the possible animations and transitions that
+users of the compound item might wish to employ. For example, a spinbox might need to smoothly
+transition from an arbitrary Text item, or characters within a Text item, so your spinbox
+item would need to be sufficiently flexible to allow such animation.
+
+*/
diff --git a/doc/src/declarative/tutorial.qdoc b/doc/src/declarative/tutorial.qdoc
new file mode 100644
index 0000000..5c855ec
--- /dev/null
+++ b/doc/src/declarative/tutorial.qdoc
@@ -0,0 +1,19 @@
+/*!
+\page tutorial.html
+\title Tutorial
+
+This tutorial gives an introduction to QML and the Fluid UI atoms. It doesn't cover everything; the emphasis is on teaching the key principles, and features are introduced as needed.
+
+Chapter one starts with a minimal "Hello world" program and the following chapters introduce new concepts.
+
+The tutorial's source code is located in the $QTDIR/examples/declarative/tutorials/helloworld directory.
+
+Tutorial chapters:
+
+\list
+\o \l {tutorial1}{Tutorial 1}
+\o \l {tutorial2}{Tutorial 2}
+\o \l {tutorial3}{Tutorial 3}
+\endlist
+
+*/
diff --git a/doc/src/declarative/tutorial1.qdoc b/doc/src/declarative/tutorial1.qdoc
new file mode 100644
index 0000000..5c11326
--- /dev/null
+++ b/doc/src/declarative/tutorial1.qdoc
@@ -0,0 +1,78 @@
+/*!
+\page tutorial1.html
+\title Tutorial 1 - Hello World!
+\target tutorial1
+
+This first program is a simple "Hello world" example. The picture below is a screenshot of this program.
+
+\image declarative-tutorial1.png
+
+Here is the QML code for the application:
+
+\code
+Rect {
+ id: Page
+ width: 480
+ height: 200
+ color: "LightGrey"
+ Text {
+ id: HelloText
+ text: "Hello world!"
+ font.size: 24
+ font.bold: true
+ y: 30
+ anchors.horizontalCenter: Page.horizontalCenter
+ }
+}
+\endcode
+
+\section1 Walkthrough
+
+\section2 Rect element
+
+\code
+Rect {
+ id: Page
+ width: 480
+ height: 200
+ color: "LightGrey"
+}
+\endcode
+
+First, we declare a root element of type \l Rect. It is one of the basic building blocks you can use to create an application in QML.
+We give it an id to be able to refer to it later. In this case, we call it \e Page. We also set the \c width, \c height and \c color properties.
+The \l Rect element contains many other properties (such as \c x and \c y), but these are left at their default values.
+
+\section2 Text element
+
+\code
+Text {
+ id: HelloText
+ text: "Hello world!"
+ font.size: 24
+ font.bold: true
+ y: 30
+ anchors.horizontalCenter: Page.horizontalCenter
+}
+\endcode
+
+We add a text element as a child of our root element to display the text 'Hello world!'.
+
+The \c y property is used to position the text vertically at 30 pixels from the top of its parent.
+
+The \c font.size and \c font.bold properties are related to fonts and use the \e 'dot' notation.
+
+The \c anchors.horizontalCenter property refers to the horizontal center of an element. In this case, we specify that our text element should be horizontally centered in the \e Page element.
+
+\section2 Viewing the example
+
+To view what you have created, run the qmlviewer (located in the \c bin directory) with your filename as the first argument. For example, to run the provided completed Tutorial 1 example from the install location, you would type:
+
+\code
+bin/qmlviewer $QTDIR/examples/declarative/tutorials/helloworld/t1/tutorial1.qml
+\endcode
+
+[\l tutorial] [Next: \l tutorial2]
+
+*/
+
diff --git a/doc/src/declarative/tutorial2.qdoc b/doc/src/declarative/tutorial2.qdoc
new file mode 100644
index 0000000..c22a01a
--- /dev/null
+++ b/doc/src/declarative/tutorial2.qdoc
@@ -0,0 +1,132 @@
+/*!
+\page tutorial2.html
+\title Tutorial 2 - Some colors
+\target tutorial2
+
+This chapter adds a color picker to change the color of the text.
+
+\image declarative-tutorial2.png
+
+Our color picker is made of many cells with different colors. To avoid writing the same code many times, we first create a new \c Cell component with a color property (see \l components).
+
+Here is the QML code for \c Cell.qml:
+
+\code
+Item {
+ property var color
+
+ id: CellContainer
+ width: 40
+ height: 25
+
+ Rect {
+ anchors.fill: parent
+ color: CellContainer.color
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { HelloText.color = CellContainer.color }
+ }
+}
+\endcode
+
+Then, we use our \c Cell component to create the color picker in the QML code for the application:
+
+\code
+Rect {
+ id: Page
+ width: 480
+ height: 200
+ color: "LightGrey"
+ 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
+ rows: 2; columns: 3
+ Cell { color: "#ff0000" }
+ Cell { color: "#00ff00" }
+ Cell { color: "#0000ff" }
+ Cell { color: "#ffff00" }
+ Cell { color: "#00ffff" }
+ Cell { color: "#ff00ff" }
+ }
+}
+\endcode
+
+\section1 Walkthrough
+
+\section2 The Cell Component
+
+\code
+Item {
+ id: CellContainer
+ width: 40
+ height: 25
+}
+\endcode
+
+The root element of our component is an \c Item. It is the most basic 'Fx' element in Qml and is often used as a container for other elements.
+
+\code
+property var color
+\endcode
+
+We declare a \c color property. This property is accessible from \e outside our component, this allows us to instantiate the cells with different colors.
+
+\code
+Rect {
+ anchors.fill: parent
+ color: CellContainer.color
+}
+\endcode
+
+Our cell component is basically a colored rectangle.
+
+The \c anchors.fill property is a convenient way to set the size of an element. In this case the \c Rect will have the same size as its parent.
+
+We bind the \c color property of this \c Rect to the color property of our component.
+
+\code
+MouseRegion {
+ anchors.fill: parent
+ onClicked: { HelloText.color = CellContainer.color }
+}
+\endcode
+
+In order to change the color of the text when clicking on a cell, we create a \c MouseRegion element with the same size as its parent.
+
+The \c onClicked property sets the \c color property of the element named \e HelloText to our cell color.
+
+\section2 The main QML file
+
+\code
+GridLayout {
+ id: ColorPicker
+ x: 0
+ anchors.bottom: Page.bottom
+ width: 120; height: 50
+ rows: 2; columns: 3
+ Cell { color: "#ff0000" }
+ Cell { color: "#00ff00" }
+ Cell { color: "#0000ff" }
+ Cell { color: "#ffff00" }
+ Cell { color: "#00ffff" }
+ Cell { color: "#ff00ff" }
+}
+\endcode
+
+In the main QML file, the only thing we have to do is to create a color picker by putting 6 cells with different colors in a grid layout.
+
+[Previous: \l tutorial1] [Next: \l tutorial3]
+
+*/
+
diff --git a/doc/src/declarative/tutorial3.qdoc b/doc/src/declarative/tutorial3.qdoc
new file mode 100644
index 0000000..0b97e63
--- /dev/null
+++ b/doc/src/declarative/tutorial3.qdoc
@@ -0,0 +1,133 @@
+/*!
+\page tutorial3.html
+\title Tutorial 3 - States
+\target tutorial3
+
+In this chapter, we make this example a little bit more dynamic by introducing states.
+
+We want our text to jump at the bottom of the screen and become red when clicked.
+
+\image declarative-tutorial3_animation.gif
+
+Here is the QML code:
+
+\code
+Rect {
+ id: Page
+ width: 480
+ height: 200
+ color: "LightGrey"
+ 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"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "down"
+ reversible: true
+ ParallelAnimation {
+ NumericAnimation {
+ properties: "y"
+ duration: 500
+ easing: "easeOutBounce"
+ }
+ ColorAnimation { duration: 500 }
+ }
+ }
+ ]
+ }
+ MouseRegion { id: MouseRegion; anchors.fill: HelloText }
+ GridLayout {
+ id: ColorPicker
+ x: 0
+ anchors.bottom: Page.bottom
+ width: 120; height: 50
+ rows: 2; columns: 3
+ Cell { color: "#ff0000" }
+ Cell { color: "#00ff00" }
+ Cell { color: "#0000ff" }
+ Cell { color: "#ffff00" }
+ Cell { color: "#00ffff" }
+ Cell { color: "#ff00ff" }
+ }
+}
+\endcode
+
+\section1 Walkthrough
+
+\code
+states: [
+ State {
+ name: "down"
+ when: MouseRegion.pressed == true
+ SetProperty {
+ target: HelloText
+ property: "y"
+ value: 160
+ }
+ SetProperty {
+ target: HelloText
+ property: "color"
+ value: "red"
+ }
+ }
+]
+\endcode
+
+First, we create a new state \e down for our text element. This state will be activated when MouseRegion is pressed, and deactivated when it is released.
+
+The \e down state includes a set of property changes from our implicit \e {default state} (the items as they were initially defined in the QML). Specifically, we set the \c y property of the text to 160 and the \c color to red.
+
+\code
+Transition {
+ fromState: "*"
+ toState: "down"
+ reversible: true
+}
+\endcode
+
+Because we don't want the text to appear at the bottom instantly but rather move smoothly, we add a transition between our two states.
+
+\c fromState and \c toState define the states between which the transition will run. In this case, we want a transition from any state to our \e down state.
+
+Because we want the same transition to be run in reverse when changing back from the \e down state to the default state, we set \c reversible to \c true. This is equivalent to writing the two transitions separately.
+
+\code
+ParallelAnimation {
+ NumericAnimation {
+ properties: "y"
+ duration: 500
+ easing: "easeOutBounce"
+ }
+ ColorAnimation { duration: 500 }
+}
+\endcode
+
+The \c ParallelAnimation element makes sure that the two animations (color and position) will start at the same time. We could also run them one after the other by using \c SequentialAnimation instead.
+
+For more details on states and transitions, see \l {states-transitions}{States and Transitions}.
+
+[Previous: \l tutorial2] [\l tutorial]
+
+*/
+
diff --git a/doc/src/images/declarative-anchors_example.png b/doc/src/images/declarative-anchors_example.png
new file mode 100644
index 0000000..293cd4b
--- /dev/null
+++ b/doc/src/images/declarative-anchors_example.png
Binary files differ
diff --git a/doc/src/images/declarative-anchors_example2.png b/doc/src/images/declarative-anchors_example2.png
new file mode 100644
index 0000000..6d3be7d
--- /dev/null
+++ b/doc/src/images/declarative-anchors_example2.png
Binary files differ
diff --git a/doc/src/images/declarative-image_tile.png b/doc/src/images/declarative-image_tile.png
new file mode 100644
index 0000000..b946a6d
--- /dev/null
+++ b/doc/src/images/declarative-image_tile.png
Binary files differ
diff --git a/doc/src/images/declarative-item_opacity1.png b/doc/src/images/declarative-item_opacity1.png
new file mode 100644
index 0000000..cde973b
--- /dev/null
+++ b/doc/src/images/declarative-item_opacity1.png
Binary files differ
diff --git a/doc/src/images/declarative-item_opacity2.png b/doc/src/images/declarative-item_opacity2.png
new file mode 100644
index 0000000..8627360
--- /dev/null
+++ b/doc/src/images/declarative-item_opacity2.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking1.png b/doc/src/images/declarative-item_stacking1.png
new file mode 100644
index 0000000..18f4148
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking1.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking2.png b/doc/src/images/declarative-item_stacking2.png
new file mode 100644
index 0000000..7a71bcd
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking2.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking3.png b/doc/src/images/declarative-item_stacking3.png
new file mode 100644
index 0000000..cde973b
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking3.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking4.png b/doc/src/images/declarative-item_stacking4.png
new file mode 100644
index 0000000..3fdf627
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking4.png
Binary files differ
diff --git a/doc/src/images/declarative-nopercent.png b/doc/src/images/declarative-nopercent.png
new file mode 100644
index 0000000..28b00a9
--- /dev/null
+++ b/doc/src/images/declarative-nopercent.png
Binary files differ
diff --git a/doc/src/images/declarative-pathattribute.png b/doc/src/images/declarative-pathattribute.png
new file mode 100644
index 0000000..57cd049
--- /dev/null
+++ b/doc/src/images/declarative-pathattribute.png
Binary files differ
diff --git a/doc/src/images/declarative-pathcubic.png b/doc/src/images/declarative-pathcubic.png
new file mode 100644
index 0000000..ffbca5d
--- /dev/null
+++ b/doc/src/images/declarative-pathcubic.png
Binary files differ
diff --git a/doc/src/images/declarative-pathquad.png b/doc/src/images/declarative-pathquad.png
new file mode 100644
index 0000000..65f1999
--- /dev/null
+++ b/doc/src/images/declarative-pathquad.png
Binary files differ
diff --git a/doc/src/images/declarative-percent.png b/doc/src/images/declarative-percent.png
new file mode 100644
index 0000000..c277055
--- /dev/null
+++ b/doc/src/images/declarative-percent.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo1.png b/doc/src/images/declarative-qtlogo1.png
new file mode 100644
index 0000000..940d159
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo1.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo2.png b/doc/src/images/declarative-qtlogo2.png
new file mode 100644
index 0000000..b1d128a
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo2.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo3.png b/doc/src/images/declarative-qtlogo3.png
new file mode 100644
index 0000000..3f2f93f
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo3.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo4.png b/doc/src/images/declarative-qtlogo4.png
new file mode 100644
index 0000000..7c8aa64
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo4.png
Binary files differ
diff --git a/doc/src/images/declarative-rect.png b/doc/src/images/declarative-rect.png
new file mode 100644
index 0000000..173759a
--- /dev/null
+++ b/doc/src/images/declarative-rect.png
Binary files differ
diff --git a/doc/src/images/declarative-rect_gradient.png b/doc/src/images/declarative-rect_gradient.png
new file mode 100644
index 0000000..f79d579
--- /dev/null
+++ b/doc/src/images/declarative-rect_gradient.png
Binary files differ
diff --git a/doc/src/images/declarative-rect_tint.png b/doc/src/images/declarative-rect_tint.png
new file mode 100644
index 0000000..3a44013
--- /dev/null
+++ b/doc/src/images/declarative-rect_tint.png
Binary files differ
diff --git a/doc/src/images/declarative-removebutton-close.png b/doc/src/images/declarative-removebutton-close.png
new file mode 100644
index 0000000..d73f8e1
--- /dev/null
+++ b/doc/src/images/declarative-removebutton-close.png
Binary files differ
diff --git a/doc/src/images/declarative-removebutton-open.png b/doc/src/images/declarative-removebutton-open.png
new file mode 100644
index 0000000..b54d797
--- /dev/null
+++ b/doc/src/images/declarative-removebutton-open.png
Binary files differ
diff --git a/doc/src/images/declarative-removebutton.gif b/doc/src/images/declarative-removebutton.gif
new file mode 100644
index 0000000..ca4d7e6
--- /dev/null
+++ b/doc/src/images/declarative-removebutton.gif
Binary files differ
diff --git a/doc/src/images/declarative-removebutton.png b/doc/src/images/declarative-removebutton.png
new file mode 100644
index 0000000..f783e6a
--- /dev/null
+++ b/doc/src/images/declarative-removebutton.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-1.png b/doc/src/images/declarative-reuse-1.png
new file mode 100644
index 0000000..c704457
--- /dev/null
+++ b/doc/src/images/declarative-reuse-1.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-2.png b/doc/src/images/declarative-reuse-2.png
new file mode 100644
index 0000000..0b6006b
--- /dev/null
+++ b/doc/src/images/declarative-reuse-2.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-3.png b/doc/src/images/declarative-reuse-3.png
new file mode 100644
index 0000000..695a725
--- /dev/null
+++ b/doc/src/images/declarative-reuse-3.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-bluerect.png b/doc/src/images/declarative-reuse-bluerect.png
new file mode 100644
index 0000000..97dbb5f
--- /dev/null
+++ b/doc/src/images/declarative-reuse-bluerect.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-focus.png b/doc/src/images/declarative-reuse-focus.png
new file mode 100644
index 0000000..f91d374
--- /dev/null
+++ b/doc/src/images/declarative-reuse-focus.png
Binary files differ
diff --git a/doc/src/images/declarative-rotation.png b/doc/src/images/declarative-rotation.png
new file mode 100644
index 0000000..994011b
--- /dev/null
+++ b/doc/src/images/declarative-rotation.png
Binary files differ
diff --git a/doc/src/images/declarative-roundrect.png b/doc/src/images/declarative-roundrect.png
new file mode 100644
index 0000000..607da81
--- /dev/null
+++ b/doc/src/images/declarative-roundrect.png
Binary files differ
diff --git a/doc/src/images/declarative-scale.png b/doc/src/images/declarative-scale.png
new file mode 100644
index 0000000..bab729e
--- /dev/null
+++ b/doc/src/images/declarative-scale.png
Binary files differ
diff --git a/doc/src/images/declarative-scalegrid.png b/doc/src/images/declarative-scalegrid.png
new file mode 100644
index 0000000..32d87125
--- /dev/null
+++ b/doc/src/images/declarative-scalegrid.png
Binary files differ
diff --git a/doc/src/images/declarative-text.png b/doc/src/images/declarative-text.png
new file mode 100644
index 0000000..c1a4112
--- /dev/null
+++ b/doc/src/images/declarative-text.png
Binary files differ
diff --git a/doc/src/images/declarative-textedit.gif b/doc/src/images/declarative-textedit.gif
new file mode 100644
index 0000000..7186eb9
--- /dev/null
+++ b/doc/src/images/declarative-textedit.gif
Binary files differ
diff --git a/doc/src/images/declarative-textformat.png b/doc/src/images/declarative-textformat.png
new file mode 100644
index 0000000..ade1b45
--- /dev/null
+++ b/doc/src/images/declarative-textformat.png
Binary files differ
diff --git a/doc/src/images/declarative-textstyle.png b/doc/src/images/declarative-textstyle.png
new file mode 100644
index 0000000..858c1bc
--- /dev/null
+++ b/doc/src/images/declarative-textstyle.png
Binary files differ
diff --git a/doc/src/images/declarative-transformorigin.png b/doc/src/images/declarative-transformorigin.png
new file mode 100644
index 0000000..fbb3b9b
--- /dev/null
+++ b/doc/src/images/declarative-transformorigin.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list-closed.png b/doc/src/images/declarative-tutorial-list-closed.png
new file mode 100644
index 0000000..4a0fee9
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list-closed.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list-open.gif b/doc/src/images/declarative-tutorial-list-open.gif
new file mode 100644
index 0000000..5b93597
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list-open.gif
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list-open.png b/doc/src/images/declarative-tutorial-list-open.png
new file mode 100644
index 0000000..16a9c94
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list-open.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list.gif b/doc/src/images/declarative-tutorial-list.gif
new file mode 100644
index 0000000..24db426
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list.gif
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list.png b/doc/src/images/declarative-tutorial-list.png
new file mode 100644
index 0000000..723fe2f
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial1.png b/doc/src/images/declarative-tutorial1.png
new file mode 100644
index 0000000..ea0000f
--- /dev/null
+++ b/doc/src/images/declarative-tutorial1.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial2.png b/doc/src/images/declarative-tutorial2.png
new file mode 100644
index 0000000..0538451
--- /dev/null
+++ b/doc/src/images/declarative-tutorial2.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial3_animation.gif b/doc/src/images/declarative-tutorial3_animation.gif
new file mode 100644
index 0000000..d2d4c63
--- /dev/null
+++ b/doc/src/images/declarative-tutorial3_animation.gif
Binary files differ
diff --git a/doc/src/index.qdoc b/doc/src/index.qdoc
index 23e8623..2d64dfe 100644
--- a/doc/src/index.qdoc
+++ b/doc/src/index.qdoc
@@ -189,6 +189,7 @@
<li><a href="qtxmlpatterns.html">XML Patterns: XQuery &amp; XPath</a></li>
<li><a href="phonon-module.html">Phonon Multimedia Framework</a></li>
<li><a href="qtscripttools.html">Script Tools Module</a></li>
+ <li><a href="qtdeclarative.html">Declarative Module</a></li>
<li><a href="activeqt.html">ActiveQt Framework</a></li>
</ul>
</td>
diff --git a/doc/src/modules.qdoc b/doc/src/modules.qdoc
index 7372994..acfd604 100644
--- a/doc/src/modules.qdoc
+++ b/doc/src/modules.qdoc
@@ -62,6 +62,7 @@
\row \o \l{QtWebKit} \o Classes for displaying and editing Web content
\row \o \l{QtXml} \o Classes for handling XML
\row \o \l{QtXmlPatterns} \o An XQuery & XPath engine for XML and custom data models
+ \row \o \l{QtDeclarative} \o An engine for declaratively building fluid user interfaces.
\row \o \l{Phonon Module}{Phonon} \o Multimedia framework classes
\row \o \l{Qt3Support} \o Qt 3 compatibility classes
\endtable
diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc
index 069541f..b66ebee 100644
--- a/doc/src/qnamespace.qdoc
+++ b/doc/src/qnamespace.qdoc
@@ -2680,5 +2680,5 @@
\value Repeat Tile the image until there is no more space. May crop the last image.
\value Round Like Repeat, but scales the images down to ensure that the last image is not cropped.
- \sa QPixmapBorders, qDrawBorderPixmap()
+ \sa qDrawBorderPixmap()
*/
diff --git a/doc/src/snippets/declarative/GroupBox.qml b/doc/src/snippets/declarative/GroupBox.qml
new file mode 100644
index 0000000..fd8d60b
--- /dev/null
+++ b/doc/src/snippets/declarative/GroupBox.qml
@@ -0,0 +1,13 @@
+ContentWrapper {
+ id: Container; width: parent.width; height: contents.height
+ children: [
+ Rect {
+ width: parent.width; height: contents.height
+ color: "white"; pen.width: 2; pen.color: "#adaeb0"; radius: 10
+ VerticalLayout {
+ id: layout; width: parent.width; margin: 5; spacing: 2
+ Content { }
+ }
+ }
+ ]
+}
diff --git a/doc/src/snippets/declarative/comments.qml b/doc/src/snippets/declarative/comments.qml
new file mode 100644
index 0000000..22e0d18
--- /dev/null
+++ b/doc/src/snippets/declarative/comments.qml
@@ -0,0 +1,9 @@
+Text {
+ text: "Hello world!" //a basic greeting
+ /*
+ We want this text to stand out from the rest so
+ we give it a large size and different font.
+ */
+ font.family: "Helvetica"
+ font.size: 24
+}
diff --git a/doc/src/snippets/declarative/content.qml b/doc/src/snippets/declarative/content.qml
new file mode 100644
index 0000000..6f9e0d8
--- /dev/null
+++ b/doc/src/snippets/declarative/content.qml
@@ -0,0 +1,7 @@
+Rect {
+ width: 200; height: 100; color: "lightgray"
+ GroupBox {
+ Text { text: "First Item" }
+ Text { text: "Second Item" }
+ }
+}
diff --git a/doc/src/snippets/declarative/drag.qml b/doc/src/snippets/declarative/drag.qml
new file mode 100644
index 0000000..3a573ad
--- /dev/null
+++ b/doc/src/snippets/declarative/drag.qml
@@ -0,0 +1,16 @@
+//! [0]
+Rect {
+ id: blurtest; width: 600; height: 200; color: "white"
+ Image {
+ id: pic; source: "qtlogo-64.png"; anchors.verticalCenter: parent.verticalCenter
+ opacity: (600.0-pic.x) / 600;
+ MouseRegion {
+ anchors.fill: parent
+ drag.target: pic
+ drag.axis: "x"
+ drag.xmin: 0
+ drag.xmax: blurtest.width-pic.width
+ }
+ }
+}
+//! [0]
diff --git a/doc/src/snippets/declarative/gradient.qml b/doc/src/snippets/declarative/gradient.qml
new file mode 100644
index 0000000..28018b8
--- /dev/null
+++ b/doc/src/snippets/declarative/gradient.qml
@@ -0,0 +1,8 @@
+Rect {
+ width: 100; height: 100
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "red" }
+ GradientStop { position: 0.33; color: "yellow" }
+ GradientStop { position: 1.0; color: "green" }
+ }
+}
diff --git a/doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml b/doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
new file mode 100644
index 0000000..accbc3e
--- /dev/null
+++ b/doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
@@ -0,0 +1,23 @@
+ListModel {
+ id: ContactModel
+ ListElement {
+ name: "Bill Smith"
+ number: "555 3264"
+ portrait: "pics/portrait.png"
+ }
+ ListElement {
+ name: "Jim Williams"
+ number: "555 5673"
+ portrait: "pics/portrait.png"
+ }
+ ListElement {
+ name: "John Brown"
+ number: "555 8426"
+ portrait: "pics/portrait.png"
+ }
+ ListElement {
+ name: "Sam Wise"
+ number: "555 0473"
+ portrait: "pics/portrait.png"
+ }
+}
diff --git a/doc/src/snippets/declarative/gridview/gridview.qml b/doc/src/snippets/declarative/gridview/gridview.qml
new file mode 100644
index 0000000..0fca789
--- /dev/null
+++ b/doc/src/snippets/declarative/gridview/gridview.qml
@@ -0,0 +1,45 @@
+//! [3]
+Rect {
+ width: 240; height: 180; color: "white"
+ // ContactModel model is defined in dummydata/ContactModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+//! [0]
+ Component {
+ id: Delegate
+ Item {
+ id: Wrapper
+ width: 80; height: 78
+ VerticalLayout {
+ Image { source: portrait; anchors.horizontalCenter: parent.horizontalCenter }
+ Text { text: name; anchors.horizontalCenter: parent.horizontalCenter }
+ }
+ }
+ }
+//! [0]
+ // Define a highlight component. Just one of these will be instantiated
+ // by each ListView and placed behind the current item.
+//! [1]
+ Component {
+ id: Highlight
+ Rect {
+ color: "lightsteelblue"
+ radius: 5
+ }
+ }
+//! [1]
+ // The actual grid
+//! [2]
+ GridView {
+ width: parent.width; height: parent.height
+ model: ContactModel; delegate: Delegate
+ cellWidth: 80; cellHeight: 80
+ highlight: Highlight
+ focus: true
+ }
+//! [2]
+}
+//! [3]
diff --git a/doc/src/snippets/declarative/gridview/pics/portrait.png b/doc/src/snippets/declarative/gridview/pics/portrait.png
new file mode 100644
index 0000000..fb5052a
--- /dev/null
+++ b/doc/src/snippets/declarative/gridview/pics/portrait.png
Binary files differ
diff --git a/doc/src/snippets/declarative/listview/dummydata/ContactModel.qml b/doc/src/snippets/declarative/listview/dummydata/ContactModel.qml
new file mode 100644
index 0000000..53c745e
--- /dev/null
+++ b/doc/src/snippets/declarative/listview/dummydata/ContactModel.qml
@@ -0,0 +1,15 @@
+ListModel {
+ id: ContactModel
+ ListElement {
+ name: "Bill Smith"
+ number: "555 3264"
+ }
+ ListElement {
+ name: "John Brown"
+ number: "555 8426"
+ }
+ ListElement {
+ name: "Sam Wise"
+ number: "555 0473"
+ }
+}
diff --git a/doc/src/snippets/declarative/listview/highlight.qml b/doc/src/snippets/declarative/listview/highlight.qml
new file mode 100644
index 0000000..e3c948e
--- /dev/null
+++ b/doc/src/snippets/declarative/listview/highlight.qml
@@ -0,0 +1,49 @@
+Rect {
+ width: 180; height: 200; color: "white"
+
+ // ContactModel model is defined in dummydata/ContactModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+//! [0]
+ Component {
+ id: Delegate
+ Item {
+ id: Wrapper
+ width: 180; height: 40
+ VerticalLayout {
+ x: 5; y: 5
+ Text { text: '<b>Name:</b> ' + name }
+ Text { text: '<b>Number:</b> ' + number }
+ }
+ }
+ }
+//! [0]
+ // 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.
+//! [1]
+ Component {
+ id: Highlight
+ Rect {
+ width: 180; height: 40
+ color: "lightsteelblue"; radius: 5
+ y: Follow {
+ source: List.current.y
+ spring: 3
+ damping: 0.1
+ }
+ }
+ }
+ ListView {
+ id: List
+ width: parent.height; height: parent.height
+ model: ContactModel; delegate: Delegate
+ highlight: Highlight
+ autoHighlight: false
+ focus: true
+ }
+//! [1]
+}
diff --git a/doc/src/snippets/declarative/listview/listview.qml b/doc/src/snippets/declarative/listview/listview.qml
new file mode 100644
index 0000000..21a5fce
--- /dev/null
+++ b/doc/src/snippets/declarative/listview/listview.qml
@@ -0,0 +1,47 @@
+//! [3]
+Rect {
+ width: 180; height: 200; color: "white"
+
+ // ContactModel model is defined in dummydata/ContactModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+//! [0]
+ Component {
+ id: Delegate
+ Item {
+ id: Wrapper
+ width: 180; height: 40
+ VerticalLayout {
+ x: 5; y: 5
+ Text { text: '<b>Name:</b> ' + name }
+ Text { text: '<b>Number:</b> ' + number }
+ }
+ }
+ }
+//! [0]
+ // Define a highlight component. Just one of these will be instantiated
+ // by each ListView and placed behind the current item.
+//! [1]
+ Component {
+ id: Highlight
+ Rect {
+ color: "lightsteelblue"
+ radius: 5
+ }
+ }
+//! [1]
+ // The actual list
+//! [2]
+ ListView {
+ width: parent.width; height: parent.height
+ model: ContactModel
+ delegate: Delegate
+ highlight: Highlight
+ focus: true
+ }
+//! [2]
+}
+//! [3]
diff --git a/doc/src/snippets/declarative/mouseregion.qml b/doc/src/snippets/declarative/mouseregion.qml
new file mode 100644
index 0000000..5c1afe6
--- /dev/null
+++ b/doc/src/snippets/declarative/mouseregion.qml
@@ -0,0 +1,23 @@
+Rect { width: 200; height: 100
+HorizontalLayout {
+//! [0]
+Rect { width: 100; height: 100; color: "green"
+ MouseRegion { anchors.fill: parent; onClicked: { parent.color = 'red' } }
+}
+//! [0]
+//! [1]
+Rect {
+ width: 100; height: 100; color: "green"
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: {
+ if (mouse.button == Qt.RightButton)
+ parent.color = 'blue';
+ else
+ parent.color = 'red';
+ }
+ }
+}
+//! [1]
+}
+}
diff --git a/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml
new file mode 100644
index 0000000..44cdaf0
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml
@@ -0,0 +1,15 @@
+ListModel {
+ id: MenuModel
+ ListElement {
+ name: "Bill Jones"
+ icon: "pics/qtlogo-64.png"
+ }
+ ListElement {
+ name: "Jane Doe"
+ icon: "pics/qtlogo-64.png"
+ }
+ ListElement {
+ name: "John Smith"
+ icon: "pics/qtlogo-64.png"
+ }
+}
diff --git a/doc/src/snippets/declarative/pathview/pathattributes.qml b/doc/src/snippets/declarative/pathview/pathattributes.qml
new file mode 100644
index 0000000..44789f2
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/pathattributes.qml
@@ -0,0 +1,34 @@
+Rect {
+ width: 240; height: 200; color: 'white'
+//! [0]
+//! [1]
+ Component {
+ id: Delegate
+ Item {
+ id: Wrapper
+ width: 80; height: 80
+ scale: PathView.scale
+ opacity: PathView.opacity
+ VerticalLayout {
+ Image { anchors.horizontalCenter: Name.horizontalCenter; width: 64; height: 64; source: icon }
+ Text { id: Name; text: name; font.size: 16}
+ }
+ }
+ }
+//! [1]
+//! [2]
+ PathView {
+ anchors.fill: parent; model: MenuModel; delegate: Delegate
+ path: Path {
+ startX: 120; startY: 100
+ PathAttribute { name: "scale"; value: 1.0 }
+ PathAttribute { name: "opacity"; value: 1.0 }
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathAttribute { name: "scale"; value: 0.3 }
+ PathAttribute { name: "opacity"; value: 0.5 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+//! [2]
+//! [0]
+}
diff --git a/doc/src/snippets/declarative/pathview/pathview.qml b/doc/src/snippets/declarative/pathview/pathview.qml
new file mode 100644
index 0000000..11df0a2
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/pathview.qml
@@ -0,0 +1,28 @@
+Rect {
+ width: 240; height: 200; color: 'white'
+//! [0]
+//! [1]
+ Component {
+ id: Delegate
+ Item {
+ id: Wrapper
+ width: 80; height: 80
+ VerticalLayout {
+ Image { anchors.horizontalCenter: Name.horizontalCenter; width: 64; height: 64; source: icon }
+ Text { id: Name; text: name; font.size: 16}
+ }
+ }
+ }
+//! [1]
+//! [2]
+ PathView {
+ anchors.fill: parent; model: MenuModel; delegate: Delegate
+ path: Path {
+ startX: 120; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+//! [2]
+//! [0]
+}
diff --git a/doc/src/snippets/declarative/pathview/pics/qtlogo-64.png b/doc/src/snippets/declarative/pathview/pics/qtlogo-64.png
new file mode 100644
index 0000000..4f68e16
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/pics/qtlogo-64.png
Binary files differ
diff --git a/doc/src/snippets/declarative/pics/qt.png b/doc/src/snippets/declarative/pics/qt.png
new file mode 100644
index 0000000..cbed1a9
--- /dev/null
+++ b/doc/src/snippets/declarative/pics/qt.png
Binary files differ
diff --git a/doc/src/snippets/declarative/repeater.qml b/doc/src/snippets/declarative/repeater.qml
new file mode 100644
index 0000000..c8f9f18
--- /dev/null
+++ b/doc/src/snippets/declarative/repeater.qml
@@ -0,0 +1,12 @@
+//! [0]
+Rect { width: 220; height: 20; color: "white"
+ Component { id: Dot
+ Rect { width: 20; height: 20; radius: 10; color: "green" }
+ }
+ HorizontalLayout {
+ Rect { width: 10; height: 20; color: "red" }
+ Repeater { component: Dot; dataSource: 10 }
+ Rect { width: 10; height: 20; color: "blue" }
+ }
+}
+//! [0]
diff --git a/doc/src/snippets/declarative/rotation.qml b/doc/src/snippets/declarative/rotation.qml
new file mode 100644
index 0000000..01838dd
--- /dev/null
+++ b/doc/src/snippets/declarative/rotation.qml
@@ -0,0 +1,27 @@
+Rect {
+ width: 360; height: 80
+ color: "white"
+//! [0]
+ HorizontalLayout {
+ margin: 10
+ spacing: 10
+ Image { source: "pics/qt.png" }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation3D { axis.startX: 30; axis.endX: 30; axis.endY: 60; angle: 18 }
+ }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation3D { axis.startX: 30; axis.endX: 30; axis.endY: 60; angle: 36 }
+ }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation3D { axis.startX: 30; axis.endX: 30; axis.endY: 60; angle: 54 }
+ }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation3D { axis.startX: 30; axis.endX: 30; axis.endY: 60; angle: 72 }
+ }
+ }
+//! [0]
+}
diff --git a/doc/src/snippets/qprocess-environment/main.cpp b/doc/src/snippets/qprocess-environment/main.cpp
index 148518b..c8681e7 100644
--- a/doc/src/snippets/qprocess-environment/main.cpp
+++ b/doc/src/snippets/qprocess-environment/main.cpp
@@ -62,7 +62,7 @@ env.insert("TMPDIR", "C:\\MyApp\\temp"); // Add an environment variable
env["PATH"] += ";C:\\Bin";
process.setEnvironment(env);
process.start("myapp");
-//! [0]
+//! [1]
}
}
diff --git a/doc/src/topics.qdoc b/doc/src/topics.qdoc
index 6ef3a89..4cc6617 100644
--- a/doc/src/topics.qdoc
+++ b/doc/src/topics.qdoc
@@ -226,6 +226,13 @@ system.
application. This tutorial is also available with
\l{Tutoriel "Carnet d'adresses"}{French explanation}.
+ \section1 \l{Declarative UI Tutorial}
+
+ \inlineimage declarative-tutorial-list-open.png
+
+ A beginner's guide to getting started with Declarative UI and QML. This
+ allows for creating user interfaces that are highly animated and
+ graphically rich.
*/
/*!
diff --git a/doc/src/tutorials/declarative.qdoc b/doc/src/tutorials/declarative.qdoc
new file mode 100644
index 0000000..3fad672
--- /dev/null
+++ b/doc/src/tutorials/declarative.qdoc
@@ -0,0 +1,674 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page tutorials-declarative-contacts.html
+ \startpage {index.html}{Qt Reference Documentation}
+ \nextpage {tutorials/declarative/contacts/part1}{Chapter 1}
+
+ \title Declarative UI Tutorial
+ \ingroup howto
+ \ingroup tutorials
+ \brief An introduction to using Qt Declarative UI to put together a
+ simple animated application.
+
+ \omit
+ At the time of writing the tutorial Declarative UI was still under
+ development. It is extremely likely that an update will be required
+ prior to 4.6 release.
+ \endomit
+
+ This tutorial gives an introduction to using the Qt Declarative UI
+ animation framework.
+
+ In this process we will learn about some of the basics of using
+ Declarative UI, such as
+
+ \list
+ \o Basic drawing
+ \o States and Transitions
+ \o Reuse of components
+ \o Models and Views
+ \endlist
+
+ An existing knowledge of Qt is not required.
+
+ The tutorial's source code is located in Qt's
+ \c examples/declarative/tutorials/contacts directory.
+ It is split up into a number of sub directories, and within each
+ sub directory the files are numbered in an order of increasing features.
+
+ The code in this example is not compiled, but interpreted at run time.
+ This means you should use the qmlviewer application provided with
+ Qt to run the examples.
+
+ \list
+ \o \l{tutorials/declarative/contacts/part1}{Drawing and Animation}
+ \o \l{tutorials/declarative/contacts/part2}{Reusing QML Components}
+ \o \l{tutorials/declarative/contacts/part3}{Models, Views and Delegates}
+ \endlist
+*/
+
+/*!
+ \page tutorials-declarative-contacts-part1.html
+ \contentspage {Declarative UI Tutorial}{Contents}
+ \nextpage {tutorials/declarative/contacts/part2}{Chapter 2}
+ \example tutorials/declarative/contacts/part1
+ \title Drawing and Animation
+ \tableofcontents
+
+ The first part of this tutorial covers basic drawing of elements on the
+ screen and causing them to animate.
+
+ \section1 Drawing
+
+ In this first chapter we will build a button that indicates something
+ can be removed and asks for confirmation. When clicked it will expand
+ from a small button with a trash can icon, to a wide button with a
+ confirm icon on the left, the text "Remove" in the middle, and a
+ cancel icon on the right.
+
+ \image declarative-removebutton.gif
+
+ Because Declarative UI is declarative, you don't pass instructions on
+ what to paint in a sequential manner as you may be used to. Instead
+ elements and how they appear on the screen are declared in much the
+ same was as elements on a web page are declared. This is done using
+ the Qt Markup Language which we will refer to by the abbreviation QML
+ for the remainder of the tutorial.
+
+ We will start by drawing a simple red rectangle with rounded corners.
+
+ \image declarative-roundrect.png
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/1/RemoveButton.qml 0
+
+ This is one of the simplest of QML components. It describes a rectangle with
+ some simple properties. In QML all components start with a capital
+ letter, and their properties with lower case letters.
+
+ Apart from the properties all QML components share, the \l{Rect}{Rect} component has the properties
+
+ \list
+ \o color - The background color of the rectangle
+ \o tintColor - The overlay color of the rectangle
+ \o gradientColor - The color at the base of the rectangle to blend upwards
+ \o pen - The description of how to draw the border of the rectangle
+ \o radius - The corner radius used to draw rounded rectangles.
+ \endlist
+
+ There are also a number of properties all QML components shares, described
+ in the \l{Item}{Item} element reference documentation. The rectangle drawn in the
+ above code uses the properties;
+
+ \list
+ \o id - An identifier of the component
+ \o width - the width of the component when drawn
+ \o height - the height of the component when drawn
+ \endlist
+
+ Currently we have described a rectangle with a width and height of 30 pixels, filled in with
+ the color red and with rounded corners using a radius of 5.
+
+ \section1 Layout
+
+ The next step of the tutorial adds an image over the rectangle. We
+ will do this by adding an \l{Image}{Image} component as a child of the
+ \l{Rect}{Rect} component. All QML components have a list of children which
+ are drawn in order after the parent component has been drawn.
+ By having the \l{Image}{Image}
+ component as a child of the \l{Rect}{Rect} component we ensure it is drawn
+ over the \l{Rect}{Rect} component. Children also are affected by the opacity
+ of the parent component and calculate their position in within the bounds of
+ the parent component.
+
+ \image declarative-removebutton-close.png
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml 0
+
+ The trashIcon image is added as a child of the Rectangle. In this case
+ the children property isn't explicitly used because the default property
+ of the \l{Rect}{Rect} component is its children. Some elements often don't have children
+ and use some other default component. When this is the case its possible
+ to explicitly list the sub component as a child as follows:
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml 0
+
+ The \l{Image}{Image} element allows loading an image file for display. The source
+ specified is a URL, and in this case refers to a portable network graphics
+ file in a relative directory to where the QML file was loaded from.
+
+ Also new in this code is the use of anchors. In QML components can either
+ have their position and size specified explicitly using x, y, width
+ and height, or they can instead specify the size and position in relation
+ to either parent or sibling elements. The \l{Image}{Image} component uses
+ a combination of both styles. It has a fixed size, but specifies its
+ position to align to the right of its parent and for its vertical center
+ to align with the vertical center of its parent. Setting a property
+ by the identifier of a separate property binds them. This means
+ that if while running the example the position of the \l{Rect}{Rect} component's
+ vertical center changed, so to would the vertical center of
+ the \l{Image}{Image} component.
+
+ The parent value is a special identifier that always refers to the
+ parent component of a component.
+
+ Anchors are most useful when the size of items might change based on
+ the component state or contents. However they are limited in that they
+ must always refer to a parent or sibling component. See
+ \l{anchor-layout}{Anchor-based Layout} for more information on using
+ anchors in QML.
+
+ At this point the initial state of the RemoveButton is complete. A small
+ rounded rectangle with a trash icon. Next we will design the open
+ state for the button.
+
+ \image declarative-removebutton-open.png
+
+ This is a wider rectangle with two images and some text. The code to
+ draw this state of the button could be written as follows:
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml 0
+
+ The rectangle width is now wider by 200 pixels. Also the trashIcon has
+ been replaced. Normally we wouldn't
+ remove the trashIcon when developing an alternate state of the RemoveButton,
+ however since this is a tutorial its been done so that its easier to
+ understand the alternate state we are aiming for and how it relates to
+ transitioning between states.
+
+ We also introduce the \l{Text}{Text} element.
+ Left and Right anchors are specified in terms of the neighboring icons
+ because we want text to fill the space between the icons. This
+ means as the parent removeButton gets wider, so will the text component.
+ It also means that if we animate a width change on the removeButton,
+ any bindings, that is the values specified by an expression such as
+ \c{parent.left} will be evaluated and animated as well.
+
+ \section1 Defining States
+
+ When designing a component with multiple states, it should be developed
+ in the initial state and the changes that would be made specified
+ as an additional state. Its not normally possible to add new children
+ to an element when changing state
+ This means that all possible child components should be included
+ in the initial state, and those that should not be visible in the initial
+ state should have their opacity set to zero. Thus
+ for the RemoveButton we specify the starting size of the RemoveButton
+ and hide any items that should not initially be visible.
+
+ The code snippet below shows what the start of the duel state specification
+ might look like.
+
+ \code
+ 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"
+ opacity: 1
+ }
+ 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
+ }
+ \endcode
+
+ The code above includes components from both states of the RemoveButton,
+ but by setting opacity="0" for the cancelIcon it means that the
+ components of the second state won't be drawn yet.
+ The base state of a component always has an empty name, however new
+ states can be added that describe how a component and its children
+ should be changed. For the RemoveButton there is only one non-base state
+ required. In this tutorial we will name it the 'opened' state.
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml states
+
+ In the opened state the width of the button itself changes from the base
+ width of 30 to the new width of 230. Also the opacity of the children
+ are changed so that the trash icon is now hidden and the other elements
+ are now visible.
+
+ \section1 Changing States
+
+ To trigger the change we will react to the 'clicked' signal of a
+ MouseRegion component.
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml mouse region
+
+ MouseRegion components handle mouse actions within their geometry. This
+ geometry behaves the same way as painted components, such that children
+ cover their parents and later siblings will cover earlier siblings and
+ all the children of the earlier sibling, should they overlap.
+
+ When a component has a signal, such as clicked, the action for the signal
+ can be specified using \c{onSignalName}, as is done above. In this
+ case when the clicked signal is emitted by the MouseRegion component,
+ a function called \c{toggle()} is called. It might also have been written
+
+ \code
+ onClicked: { removeButton.state='opened' }
+ \endcode
+
+ However in this case we are using a function because it allows multiple
+ mouse regions to use the same functionality, and also makes it
+ easier to specify complex behavior in response to a signal.
+
+ An alternative would be to explicitly state the connection:
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml mouse region
+
+ This will connect to the \c{clicked()} signal of the trashMouseRegion component
+ and execute the associated script.
+
+ The \c{toggle()} function is a new function specified as part of the remove
+ button element.
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml script
+
+ Any QML component can have a set of resources specified. One of those
+ resources is any Script that might be needed. See the
+ \l{QtScript Module} for more information on how to write
+ script code in Qt.
+
+ It is possible to refer to identified QML components
+ within the script. Hence the function for our RemoveButton will check
+ if the state is already open to determine what the new state should be.
+
+ \section1 Animation
+
+ Currently the RemoveButton is functional, but snaps between our two states.
+ Fortunately making the transition between states smooth is very simple.
+ We only need one more bit of code at the end of our removeButton component.
+
+ \snippet declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml transition
+
+ All QML components have a transitions property. This describes how
+ properties of items within the component should change. In this case
+ we specify that if the x, width or opacity of the removeButton or its
+ children change due to a change in state, that they should take 200ms
+ to complete their transition.
+
+ \omit
+ TODO More on types of animation, e.g. ColorAnimation, Behaviors.
+ \endomit
+
+ In the next chapter we will show how we can use the remove button in
+ other QML components.
+*/
+
+/*!
+ \page tutorials-declarative-contacts-part2.html
+ \contentspage {Declarative UI Tutorial}{Contents}
+ \previouspage {tutorials/declarative/contacts/part1}{Chapter 1}
+ \nextpage {tutorials/declarative/contacts/part3}{Chapter 3}
+ \example tutorials/declarative/contacts/part2
+ \title Reusing QML Components
+ \tableofcontents
+
+ The second part of this tutorial covers how to reuse QML components and
+ have them interact with each other. The RemoveButton developed in the
+ previous chapter is intended to be part of a more complex control for
+ editing a field of our contact. This ContactField in turn is intended
+ to be used in a contact editing control.
+
+ \image declarative-reuse-3.png
+
+ \section1 Loading QML Components
+
+ Reusing the RemoveButton itself is very simple. When parsing a QML file
+ if a Component is referred to that isn't already in the system, Qt
+ will try to load it from a file of the same name with the ".qml" extension.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/1/ContactField.qml load
+
+ The above QML code will attempt to load the RemoveButton component from
+ a file with the name "RemoveButton.qml" from the following search paths.
+
+ \list
+ \o Any imported directories. These are listed at the start of the file using
+ \c { import "path" }.
+ \o the directory of the QML code file
+ \endlist
+
+ All the properties of the button are
+ accessible and can be overridden from defaults. The loaded component
+ can also refer to elements further up in the tree, so that code within
+ RemoveButton.qml could refer to the contactField component.
+ Only properties of the top level element in RemoveButton.qml are visible to
+ the contact field.
+
+ There are also two other ways to reuse components in QML. A component
+ can be reused from within the same QML file using Component and ComponentInstance
+ elements. The next code snippet produces three red rounded rectangles
+ within a large blue rectangle.
+
+ \image declarative-reuse-bluerect.png
+
+ \snippet declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml all
+
+ This can be useful when the component is not complex enough to justify its
+ own file. The third way to reuse components allows for delaying loading
+ of the QML until some later event. Each \l{Item}{Item} includes
+ a special child, qmlItem, which has its definition provided by the
+ contents of the qml property of its parent.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml load
+
+ This last method is useful if the contents of a item need to change at
+ run time or if the initial complexity of the loaded QML needs to be
+ reduced in order to improve the time it takes to start the application. In
+ chapter three this method is used to improve performance of
+ scrolling through very large numbers of items.
+
+ Because of its simplicity, the first method is the recommended in most
+ cases and will be the focus of the remainder of this chapter.
+
+ \section1 Properties and Signals
+
+ The next task is to be able to control aspects of the RemoveButton from
+ the components that use it. In particular controlling how far it
+ expands and how it reacts when the user clicks on the confirm icon
+ of the remove button. When reusing a component in a separate QML file
+ only the attributes of the root element are visible. To allow controlling
+ attributes of child elements within an imported component we need to define
+ some properties and signals for the RemoveButton.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml define properties and signals
+
+ The children of the remove button can use these properties and signals. The
+ opened state can now bind the expanded width to the expandedWidth property.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml use width
+
+ Also when the confirm icon is clicked, as well as toggling the state it will
+ emit the confirmed signal of the RemoveButton component.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml use signal
+
+ These properties and signals can also be accessed from the contact field the same
+ way standard system component properties and signals are accessed.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/2/ContactField.qml use properties and signals
+
+ Now when the remove button is expanded, it will expand to the width of the
+ contact field. Also when the user confirms the remove action, the
+ text section of the contact field will be cleared.
+
+ \section1 States
+
+ Its also possible to access the state of included components. The FieldText
+ component we will use in this tutorial is also been written specifically
+ for our contacts application. In
+ this case we want it to expand when editing. One way to do this would
+ be to anchor the field text component to the center of its parent and
+ then let its own width change push the remove button away, however that
+ would make it difficult to have the remove button also push the field
+ text to the left when the remove button expands. Instead we will anchor
+ the right edge of the field text to the left edge of the remove button
+ and use a state change in the contact field itself to move the
+ remove button and the field icon out of
+ view.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/3/ContactField.qml all
+
+ Apart from accessing the fieldText.state, the above code also uses the when
+ attribute of its own editingText state. This is an alternative to using
+ a signal to change state. When the value of the expression for the
+ when attribute changes, Qt will detect if the contactField needs to enter
+ that state. In the FieldText element a similar approach is used to fade
+ out the label of the FieldText when the user enters some text of their own.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/3/FieldText.qml behavior
+
+ \c{fieldText} is the enclosing component and \c{textEdit} is a TextEdit element
+ provided by Qt. In the QML code above, the opacity of the textLabel is
+ only 1 if the text for the textEdit is empty. This is a form of
+ short cut to using states for an element, useful if only one property
+ is changing as it is for the textLabel. To animate a property change is
+ similar to animating a state change. Using the Behavior element we can
+ specify how the property changes if it does change state, allowing for
+ a smooth transition.
+
+ \section1 Key and Mouse Focus
+
+ Setting focus to true on a component does not always mean
+ that the component has focus. This is due to the declarative nature
+ of QML, and can be affected by multiple components both indicating
+ focus to be true. At the time of writing this tutorial both key and mouse
+ focus handling are still being improved. Hence we will only lightly cover
+ the topic.
+
+ For an item to have key focus in QML it is required that:
+
+ \list
+ \o If there is a FocusRealm ancestor of the component that it has focus as well.
+ \o That it is the most recent component within the focus realms descendent's
+ to receive focus
+ \endlist
+
+ The read-only property activeFocus can be used to determine whether a
+ component will receive key input. Any un-handled keys will be passed to
+ the components parent, which in turn will pass keys it doesn't handle up to its
+ own ancestors.
+
+ Some components such as ListView components are also FocusRealm components, as they
+ handle focus among the child list items.
+
+ At this stage of the tutorial it is sufficient to use the setting of 'focus'
+ as we only have a list of line edits and only one should be active at any given time.
+
+ Currently if multiple contact fields were put into our contact editor,
+ any of the FieldText components could be clicked and opened, and
+ any of the RemoveButton components could be clicked and opened, all
+ at the same time. This leads to situations where the users actions
+ are ambiguous
+
+ \image declarative-reuse-focus.png
+
+ To counteract this we will add a property of the root element to indicate
+ when an element has 'grabbed' mouse interaction, preventing other
+ clickable elements from reacting.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/4/Contact.qml grab property
+
+ The code that we want to disable then simply needs to check this property before
+ acting.
+
+ \snippet declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml grab
+
+ \note Handling Key and Mouse focus in QML is quite likely to change before
+ the Qt 4.6 release.
+*/
+
+/*!
+ \page tutorials-declarative-contacts-part3.html
+ \contentspage {Declarative UI Tutorial}{Contents}
+ \previouspage {tutorials/declarative/contacts/part2}{Chapter 2}
+ \example tutorials/declarative/contacts/part3
+ \title Models, Views and Delegates
+ \tableofcontents
+
+ In the previous chapters we designed a component to display and
+ edit a contact. The next step is to display a list of those contacts
+ and allow the user to expand individual contacts for editing.
+
+ As the previous elements will not be changed in this section, they have
+ been moved to a lib directory for this tutorial and the relevant
+ import path has been used.
+
+ \section1 Simple List View
+
+ Displaying lists requires three components. A model that holds the
+ data displayed, a delegate to indicate how elements are drawn and
+ a view to arrange the elements.
+
+ \image declarative-tutorial-list.gif
+
+ For the purposes of this tutorial we will be using an SQL query as our
+ data model. This can be declared in the resources section of
+ the parent item.
+
+ \snippet declarative/tutorials/contacts/3_Collections/1/ContactView.qml model
+
+ The SqlConnection component describes how to connect to the database in
+ much the same ways as the QSqlDatabase::addDatabase() function is used.
+ In this case an SQLite database is used as it can be connected to as a
+ file, reducing complexity in setting up a database server or credentials.
+
+ The SqlQuery component allows various forms of queries to be described.
+ When the query is a select statement, the component also acts as a model
+ allowing it to provide data to a ListView component. The query above
+ retrieves the fields recid, label, email and phone from a contacts table,
+ and orders the results by the label of the contact first, and then by
+ the recid for any contacts with equivalent labels.
+
+ The ListView component is suitable for displaying models and is declared
+ much like any other QML component. The ListView component also has
+ a delegate property that defines how to construct components for items in the list.
+
+ \snippet declarative/tutorials/contacts/3_Collections/1/ContactView.qml delegate
+
+ Unlike a child element, this describes a template on how to build the component
+ for each element, much in the same way that components are loaded from
+ files such as RemoveButton.qml. The are constructed or destroyed as items
+ scroll into our out of the visible area of the list.
+
+ The entire view component will look like:
+
+ \snippet declarative/tutorials/contacts/3_Collections/1/ContactView.qml view
+
+ This gives us a list of contacts that the user can flick through.
+
+ \section1 Animating Delegates
+
+ The next step is to allow the user to click on a contact to edit the
+ contact. We will take advantage of QML to open a Contact component
+ in the list rather than as a new dialog or view. This is very
+ similar to how the contents of the FieldText and RemoveButton components
+ are swapped in and out.
+
+ \image declarative-tutorial-list-open.gif
+
+ \snippet declarative/tutorials/contacts/3_Collections/2/ContactView.qml components
+
+ The first step is to have two children of our delegate component that can
+ be swapped between. The plain Text component and the Contact component built
+ in the previous chapters. We also add a MouseRegion that can be clicked upon
+ to change the state of the delegate component.
+
+ \snippet declarative/tutorials/contacts/3_Collections/2/ContactView.qml states
+
+ This defines the open state of the delegate. It changes the height of the delegate
+ component to that of the whole list view, pushing the other items off each end of
+ the list. It sets the lists views scroll yPosition of the ListView to the
+ y value of the delegate so that the top of the delegate matches the top of the list view.
+ The next step is to lock the list view. This prevents the user being able to flick
+ the list view. The final to properties that are set should
+ be familiar from previous chapters, setting the opacity of the items such
+ that the new item is visible and the old item hidden.
+
+ We then add a transition so that this becomes animated:
+
+ \snippet declarative/tutorials/contacts/3_Collections/2/ContactView.qml transitions
+
+ This allows the user to click on an item to enter the open state. Elsewhere on our
+ contact view we add a button so that the user can leave the detailed view of the contact.
+
+ \snippet declarative/tutorials/contacts/3_Collections/2/ContactView.qml button
+
+ And connect it's clicked value to some script to set the state of the delegate
+ back to its default state.
+
+ \snippet declarative/tutorials/contacts/3_Collections/2/ContactView.qml connections
+
+ Something worth noting at this point is that every delegate created has this connection.
+ It is important to check whether the delegate is the one in the open state, and
+ taking some effort to ensure only one is, before acting on the signal from the button.
+
+ \section1 Performance Considerations
+
+ We have now made a contact application that can view a list of contacts, open one,
+ and close it again. Its now time to take a moment and consider the implications
+ of a list view delegate. It is created for each and every item in the list,
+ and while the list cleans up after itself and only has delegate components constructed
+ for visible items and any single point of animation, the list can scroll very quickly.
+ This means potentially thousands of delegate components will be constructed and
+ destroyed when the user is flicking through the list.
+
+ Its important then to try and minimize the complexity of the delegate. This
+ can be done by delaying the loading of the component. By using the qml property
+ of the \l{Item}{Item} component, we can delay building the Contact.qml item until the user
+ attempts to open the list.
+
+ \snippet declarative/tutorials/contacts/3_Collections/3/ContactView.qml setting qml
+
+ Each item has a qml property that represents the filename for the contents of
+ a special qmlItem child of the \l{Item}{Item}. By setting the qml property of the Details
+ component on clicking the mouse region, the more complex component isn't loaded
+ until needed. The down side about this though is the properties of Contact
+ cannot be set until the item is loaded. This requires using the Bind element.
+
+
+ \snippet declarative/tutorials/contacts/3_Collections/3/ContactView.qml binding
+
+ Unlike binding a value to the property of a component directly, the Bind element
+ allows both the target and the property set to themselves be to dynamic values.
+ This means that when the qml property is set, it will change the
+ qmlItem property of the Details component. This in turn triggers the Bind
+ elements to set the required properties of the qmlItem, which is now
+ an instance of the Contact component.
+*/
diff --git a/examples/declarative/animation/animation.qml b/examples/declarative/animation/animation.qml
new file mode 100644
index 0000000..5cb471e
--- /dev/null
+++ b/examples/declarative/animation/animation.qml
@@ -0,0 +1,51 @@
+Rect {
+ width: 400
+ height: 200
+ color: "white"
+ Rect {
+ width: 40
+ height: 40
+ y: 80
+ color: "#FF0000"
+ radius: 10
+ // Animate the x property. Setting repeat to true makes the
+ // animation repeat indefinitely, otherwise it would only run once.
+ x: 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
+ }
+ }
+ // Alternate color between red and green
+ color: SequentialAnimation {
+ running: true
+ repeat: true
+ ColorAnimation {
+ from: "#FF0000"
+ to: "#00FF00"
+ duration: 5000
+ }
+ ColorAnimation {
+ from: "#00FF00"
+ to: "#FF0000"
+ duration: 5000
+ }
+ }
+ }
+}
diff --git a/examples/declarative/aspectratio/face_fit.qml b/examples/declarative/aspectratio/face_fit.qml
new file mode 100644
index 0000000..35c63ce
--- /dev/null
+++ b/examples/declarative/aspectratio/face_fit.qml
@@ -0,0 +1,26 @@
+// The Image primitive does not have any special handling for maintaining
+// aspect ratio. This example shows that you can provide whatever specific
+// behaviour you like.
+//
+// Here, we implement a hybrid of the "scale to fit" and "scale and crop"
+// behaviours which will crop up to 25% from *one* dimension if necessary
+// to fully scale the other. This is a realistic algorithm, for example
+// when the edges of the image contain less vital information than the
+// center - such as a face.
+//
+Rect {
+ // default size: whole image, unscaled
+ width: Image.width
+ height: Image.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: Image
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: Math.max(Math.min(parent.width/width*1.333,parent.height/height),
+ Math.min(parent.width/width,parent.height/height*1.333))
+ }
+}
diff --git a/examples/declarative/aspectratio/face_fit_animated.qml b/examples/declarative/aspectratio/face_fit_animated.qml
new file mode 100644
index 0000000..366d27b
--- /dev/null
+++ b/examples/declarative/aspectratio/face_fit_animated.qml
@@ -0,0 +1,28 @@
+// The Image primitive does not have any special handling for maintaining
+// aspect ratio. This example shows that you can provide whatever specific
+// behaviour you like.
+//
+// Here, we extend the "face_fit" example with animation to show how truly
+// diverse and usage-specific behaviours are made possible by NOT putting a
+// hard-coded aspect ratio feature into the Image primitive.
+//
+Rect {
+ // default size: whole image, unscaled
+ width: Image.width
+ height: Image.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: Image
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: Follow {
+ source: Math.max(Math.min(Image.parent.width/Image.width*1.333,Image.parent.height/Image.height),
+ Math.min(Image.parent.width/Image.width,Image.parent.height/Image.height*1.333))
+ spring: 1
+ damping: 0.05
+ }
+ }
+}
diff --git a/examples/declarative/aspectratio/pics/face.png b/examples/declarative/aspectratio/pics/face.png
new file mode 100644
index 0000000..9623b1a
--- /dev/null
+++ b/examples/declarative/aspectratio/pics/face.png
Binary files differ
diff --git a/examples/declarative/aspectratio/scale_and_crop.qml b/examples/declarative/aspectratio/scale_and_crop.qml
new file mode 100644
index 0000000..a5409f9
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_and_crop.qml
@@ -0,0 +1,21 @@
+// The Image primitive does not have any special handling for maintaining
+// aspect ratio. This example shows that you can provide whatever specific
+// behaviour you like.
+//
+// Here, we implement "Scale and Crop" behaviour.
+//
+Rect {
+ // default size: whole image, unscaled
+ width: Image.width
+ height: Image.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: Image
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: Math.max(parent.width/width,parent.height/height)
+ }
+}
diff --git a/examples/declarative/aspectratio/scale_and_sidecrop.qml b/examples/declarative/aspectratio/scale_and_sidecrop.qml
new file mode 100644
index 0000000..e076735
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_and_sidecrop.qml
@@ -0,0 +1,22 @@
+// The Image primitive does not have any special handling for maintaining
+// aspect ratio. This example shows that you can provide whatever specific
+// behaviour you like.
+//
+// Here, we implement a variant of "Scale and Crop" behaviour, where we
+// crop the sides if necessary to fully fit vertically, but not the reverse.
+//
+Rect {
+ // default size: whole image, unscaled
+ width: Image.width
+ height: Image.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: Image
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: parent.height/height
+ }
+}
diff --git a/examples/declarative/aspectratio/scale_to_fit.qml b/examples/declarative/aspectratio/scale_to_fit.qml
new file mode 100644
index 0000000..61a4082
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_to_fit.qml
@@ -0,0 +1,21 @@
+// The Image primitive does not have any special handling for maintaining
+// aspect ratio. This example shows that you can provide whatever specific
+// behaviour you like.
+//
+// Here, we implement "Scale to Fit" behaviour.
+//
+Rect {
+ // default size: whole image, unscaled
+ width: Image.width
+ height: Image.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: Image
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: Math.min(parent.width/width,parent.height/height)
+ }
+}
diff --git a/examples/declarative/behaviours/MyRect.qml b/examples/declarative/behaviours/MyRect.qml
new file mode 100644
index 0000000..dc9a094
--- /dev/null
+++ b/examples/declarative/behaviours/MyRect.qml
@@ -0,0 +1,11 @@
+Rect {
+ radius: 15
+ pen.color: "black"
+ width: 100
+ height: 100
+ id: Page
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { bluerect.parent = Page; bluerect.x=0 }
+ }
+}
diff --git a/examples/declarative/behaviours/test.qml b/examples/declarative/behaviours/test.qml
new file mode 100644
index 0000000..bb7109e
--- /dev/null
+++ b/examples/declarative/behaviours/test.qml
@@ -0,0 +1,103 @@
+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
+ }
+ }
+ NumericAnimation {
+ target: bluerect
+ property: "x"
+ duration: 500
+ }
+ }
+ 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
+ }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/connections/connections.qml b/examples/declarative/connections/connections.qml
new file mode 100644
index 0000000..e66875a
--- /dev/null
+++ b/examples/declarative/connections/connections.qml
@@ -0,0 +1,29 @@
+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(mouse)"
+ script: {
+
+ color="green";
+ dot.x = mouse.x-1;
+ dot.y = mouse.y-1;
+
+ }
+ }
+}
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..6cd42df
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/Dial.qml
@@ -0,0 +1,34 @@
+Item {
+ property real value : 0
+
+ width: 210; height: 210
+
+ Image { id: Background; source: "background.png" }
+
+ Image {
+ x: 93
+ y: 35
+ source: "needle_shadow.png"
+ transform: Rotation {
+ originX: 11; originY: 67
+ angle: NeedleRotation.angle
+ }
+ }
+ Image {
+ id: Needle
+ x: 95
+ y: 33
+ source: "needle.png"
+ transform: Rotation {
+ id: NeedleRotation
+ originX: 7; originY: 65
+ angle: -130
+ angle: Follow {
+ spring: 1.4
+ damping: .15
+ source: Math.min(Math.max(-130, value*2.2 - 130), 133)
+ }
+ }
+ }
+ Image { x: 21; y: 18; source: "overlay.png" }
+}
diff --git a/examples/declarative/dial/DialLibrary/background.png b/examples/declarative/dial/DialLibrary/background.png
new file mode 100644
index 0000000..75d555d
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/background.png
Binary files differ
diff --git a/examples/declarative/dial/DialLibrary/needle.png b/examples/declarative/dial/DialLibrary/needle.png
new file mode 100644
index 0000000..2d19f75
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/needle.png
Binary files differ
diff --git a/examples/declarative/dial/DialLibrary/needle_shadow.png b/examples/declarative/dial/DialLibrary/needle_shadow.png
new file mode 100644
index 0000000..8d8a928
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/needle_shadow.png
Binary files differ
diff --git a/examples/declarative/dial/DialLibrary/overlay.png b/examples/declarative/dial/DialLibrary/overlay.png
new file mode 100644
index 0000000..3860a7b
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/overlay.png
Binary files differ
diff --git a/examples/declarative/dial/dial.qml b/examples/declarative/dial/dial.qml
new file mode 100644
index 0000000..b183798
--- /dev/null
+++ b/examples/declarative/dial/dial.qml
@@ -0,0 +1,31 @@
+import "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
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "steelblue" }
+ GradientStop { position: 1.0; color: "lightsteelblue" }
+ }
+ radius: 8; opacity: 0.7
+ Rect {
+ id: Slider
+ x: 2; y: 2; width: 30; height: 12
+ radius: 6
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightgray" }
+ GradientStop { position: 1.0; color: "gray" }
+ }
+ MouseRegion {
+ anchors.fill: parent
+ drag.target: parent; drag.axis: "x"; drag.xmin: 2; drag.xmax: 128
+ }
+ }
+ }
+}
diff --git a/examples/declarative/easing/easing.qml b/examples/declarative/easing/easing.qml
new file mode 100644
index 0000000..af675d1
--- /dev/null
+++ b/examples/declarative/easing/easing.qml
@@ -0,0 +1,92 @@
+Rect {
+ id: Window
+ width: 640
+ height: Layout.height
+ color: "white"
+
+ ListModel {
+ id: EasingTypes
+ ListElement { type: "easeLinear" }
+ ListElement { type: "easeInQuad" }
+ ListElement { type: "easeOutQuad" }
+ ListElement { type: "easeInOutQuad" }
+ ListElement { type: "easeOutInQuad" }
+ ListElement { type: "easeInCubic" }
+ ListElement { type: "easeOutCubic" }
+ ListElement { type: "easeInOutCubic" }
+ ListElement { type: "easeOutInCubic" }
+ ListElement { type: "easeInQuart" }
+ ListElement { type: "easeOutQuart" }
+ ListElement { type: "easeInOutQuart" }
+ ListElement { type: "easeOutInQuart" }
+ ListElement { type: "easeInQuint" }
+ ListElement { type: "easeOutQuint" }
+ ListElement { type: "easeInOutQuint" }
+ ListElement { type: "easeOutInQuint" }
+ ListElement { type: "easeInSine" }
+ ListElement { type: "easeOutSine" }
+ ListElement { type: "easeInOutSine" }
+ ListElement { type: "easeOutInSine" }
+ ListElement { type: "easeInExpo" }
+ ListElement { type: "easeOutExpo" }
+ ListElement { type: "easeInOutExpo" }
+ ListElement { type: "easeOutInExpo" }
+ ListElement { type: "easeInCirc" }
+ ListElement { type: "easeOutCirc" }
+ ListElement { type: "easeInOutCirc" }
+ ListElement { type: "easeOutInCirc" }
+ ListElement { type: "easeInElastic" }
+ ListElement { type: "easeOutElastic" }
+ ListElement { type: "easeInOutElastic" }
+ ListElement { type: "easeOutInElastic" }
+ ListElement { type: "easeInBack" }
+ ListElement { type: "easeOutBack" }
+ ListElement { type: "easeInOutBack" }
+ ListElement { type: "easeOutInBack" }
+ ListElement { type: "easeOutBounce" }
+ ListElement { type: "easeInBounce" }
+ ListElement { type: "easeInOutBounce" }
+ ListElement { type: "easeOutInBounce" }
+ }
+
+ 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
+ }
+ }
+ children: [
+ MouseRegion {
+ onClicked: { Anim.running=true }
+ anchors.fill: parent
+ }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/follow/follow.qml b/examples/declarative/follow/follow.qml
new file mode 100644
index 0000000..3258ea6
--- /dev/null
+++ b/examples/declarative/follow/follow.qml
@@ -0,0 +1,50 @@
+Rect {
+ color: "#ffffff"
+ width: 320; height: 240
+ Rect {
+ id: Rect
+ color: "#00ff00"
+ y: 200; width: 60; height: 20
+ y: SequentialAnimation {
+ running: true; repeat: true
+ NumericAnimation {
+ to: 20; duration: 500
+ easing: "easeInOutQuad"
+ }
+ NumericAnimation {
+ to: 200; duration: 2000
+ easing: "easeOutBounce"
+ }
+ PauseAnimation { duration: 1000 }
+ }
+ }
+
+ // Velocity
+ Rect {
+ color: "#ff0000"
+ x: Rect.width; width: Rect.width; height: 20
+ y: Follow { source: Rect.y; velocity: 200 }
+ }
+ Text { x: Rect.width; y: 220; text: "Velocity" }
+
+ // Spring
+ Rect {
+ color: "#ff0000"
+ x: Rect.width * 2; width: Rect.width; height: 20
+ y: Follow { source: Rect.y; spring: 1.2; damping: 0.1 }
+ }
+ 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 }
+ y: Follow { source: Mouse.mouseY-10; spring: 1.0; damping: 0.05 }
+ }
+ }
+}
diff --git a/examples/declarative/follow/pong.qml b/examples/declarative/follow/pong.qml
new file mode 100644
index 0000000..582b04c
--- /dev/null
+++ b/examples/declarative/follow/pong.qml
@@ -0,0 +1,67 @@
+Rect {
+ id: Page
+ width: 640; height: 480
+ color: "#000000"
+
+ // Make a ball to bounce
+ Rect {
+ // Add a property for the target y coordinate
+ property var targetY : Page.height-10
+ property var direction : "right"
+
+ id: Ball
+ color: "#00ee00"
+ x: 20; width: 20; height: 20; z: 1
+
+ // Move the ball to the right and back to the left repeatedly
+ x: 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" }
+ }
+
+ // Make y follow the target y coordinate, with a velocity of 200
+ y: Follow { source: Ball.targetY; velocity: 200 }
+
+ // Detect the ball hitting the top or bottom of the view and bounce it
+ onTopChanged: {
+ if (y <= 0)
+ targetY = Page.height-20;
+ else if (y >= Page.height-20)
+ targetY = 0;
+ }
+ }
+
+ // 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'
+ }
+ }
+ Rect {
+ id: RightBat
+ color: "#00ee00"
+ x: Page.width-22; width: 20; height: 90
+ y: Follow {
+ source: Ball.y-45; velocity: 300
+ enabled: Ball.direction == 'right'
+ }
+ }
+
+ // The rest, to make it look realistic, if neither ever scores...
+ Rect { color: "#00ee00"; x: 320-80; y: 0; width: 40; height: 60 }
+ Rect { color: "#000000"; x: 320-70; y: 10; width: 20; height: 40 }
+ Rect { color: "#00ee00"; x: 320+40; y: 0; width: 40; height: 60 }
+ Rect { color: "#000000"; x: 320+50; y: 10; width: 20; height: 40 }
+ Repeater {
+ dataSource: 24
+ Rect { color: "#00ee00"; x: 320-5; y: index*20; width: 10; height: 10 }
+ }
+}
diff --git a/examples/declarative/listview/content/MediaButton.qml b/examples/declarative/listview/content/MediaButton.qml
new file mode 100644
index 0000000..cad36bd
--- /dev/null
+++ b/examples/declarative/listview/content/MediaButton.qml
@@ -0,0 +1,37 @@
+Item {
+ property var text
+ signal clicked
+
+ id: Container
+ Image {
+ id: Image
+ source: "pics/button.png"
+ }
+ Image {
+ id: Pressed
+ source: "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
+ states: [
+ State {
+ name: "Pressed"
+ when: MouseRegion.pressed == true
+ SetProperties {
+ target: Pressed
+ opacity: 1
+ }
+ }
+ ]
+}
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/moreDown.png b/examples/declarative/listview/content/pics/moreDown.png
new file mode 100644
index 0000000..31a35d5
--- /dev/null
+++ b/examples/declarative/listview/content/pics/moreDown.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/moreUp.png b/examples/declarative/listview/content/pics/moreUp.png
new file mode 100644
index 0000000..fefb9c9
--- /dev/null
+++ b/examples/declarative/listview/content/pics/moreUp.png
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..4d76ff4
--- /dev/null
+++ b/examples/declarative/listview/dummydata/MyPetsModel.qml
@@ -0,0 +1,59 @@
+// ListModel allows free form list models to be defined and populated.
+// Be sure to name the file the same as the id.
+ListModel {
+ id: MyListElementsModel
+ ListElement {
+ name: "Polly"
+ type: "Parrot"
+ age: 12
+ size: "Small"
+ }
+ ListElement {
+ name: "Penny"
+ type: "Turtle"
+ age: 4
+ size: "Small"
+ }
+ ListElement {
+ name: "Warren"
+ type: "Rabbit"
+ age: 2
+ size: "Small"
+ }
+ ListElement {
+ name: "Spot"
+ type: "Dog"
+ age: 9
+ size: "Medium"
+ }
+ ListElement {
+ name: "Whiskers"
+ type: "Cat"
+ age: 2
+ size: "Medium"
+ }
+ ListElement {
+ name: "Joey"
+ type: "Kangaroo"
+ age: 1
+ size: "Medium"
+ }
+ ListElement {
+ name: "Kimba"
+ type: "Bunny"
+ age: 65
+ size: "Large"
+ }
+ ListElement {
+ name: "Rover"
+ type: "Dog"
+ age: 5
+ size: "Large"
+ }
+ ListElement {
+ name: "Tiny"
+ type: "Elephant"
+ age: 15
+ size: "Large"
+ }
+}
diff --git a/examples/declarative/listview/dummydata/Recipes.qml b/examples/declarative/listview/dummydata/Recipes.qml
new file mode 100644
index 0000000..52225dd
--- /dev/null
+++ b/examples/declarative/listview/dummydata/Recipes.qml
@@ -0,0 +1,88 @@
+ListModel {
+ id: Recipes
+ ListElement {
+ title: "Pancakes"
+ picture: "content/pics/pancakes.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 1 cup (150g) self-raising flour
+ <li> 1 tbs caster sugar
+ <li> 3/4 cup (185ml) milk
+ <li> 1 egg
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
+ <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
+ <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
+ <li> Turn over and cook other side until golden.
+ </ol>
+ </html>"
+ }
+ ListElement {
+ title: "Fruit Salad"
+ picture: "content/pics/fruit-salad.jpg"
+ ingredients: "* Seasonal Fruit"
+ method: "* Chop fruit and place in a bowl."
+ }
+ ListElement {
+ title: "Vegetable Soup"
+ picture: "content/pics/vegetable-soup.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 1 onion
+ <li> 1 turnip
+ <li> 1 potato
+ <li> 1 carrot
+ <li> 1 head of celery
+ <li> 1 1/2 litres of water
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Chop vegetables.
+ <li> Boil in water until vegetables soften.
+ <li> Season with salt and pepper to taste.
+ </ol>
+ </html>"
+ }
+ ListElement {
+ title: "Hamburger"
+ picture: "content/pics/hamburger.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 500g minced beef
+ <li> Seasoning
+ <li> lettuce, tomato, onion, cheese
+ <li> 1 hamburger bun for each burger
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Mix the beef, together with seasoning, in a food processor.
+ <li> Shape the beef into burgers.
+ <li> Grill the burgers for about 5 mins on each side (until cooked through)
+ <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
+ </ol>
+ </html>"
+ }
+ ListElement {
+ title: "Lemonade"
+ picture: "content/pics/lemonade.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 1 cup Lemon Juice
+ <li> 1 cup Sugar
+ <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
+ <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
+ <li> Chill or serve over ice cubes.
+ </ol>
+ </html>"
+ }
+}
diff --git a/examples/declarative/listview/highlight.qml b/examples/declarative/listview/highlight.qml
new file mode 100644
index 0000000..9a672d9
--- /dev/null
+++ b/examples/declarative/listview/highlight.qml
@@ -0,0 +1,57 @@
+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 }
+ }
+ // 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "x"; duration: 200
+ }
+ }
+ ]
+ }
+ }
+ // 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 }
+ }
+ }
+ ListView {
+ id: List1
+ width: 200; height: parent.height
+ model: MyPetsModel; delegate: PetDelegate
+ highlight: PetHighlight; autoHighlight: false
+ focus: true
+ }
+}
diff --git a/examples/declarative/listview/listview.qml b/examples/declarative/listview/listview.qml
new file mode 100644
index 0000000..a222378
--- /dev/null
+++ b/examples/declarative/listview/listview.qml
@@ -0,0 +1,80 @@
+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 }
+ }
+ }
+ }
+
+ // 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" }
+ }
+
+ // 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: 125; width: 200; height: 50
+ color: "#FFFF88"; z: -1
+ }
+ ]
+ }
+}
diff --git a/examples/declarative/listview/recipes.qml b/examples/declarative/listview/recipes.qml
new file mode 100644
index 0000000..ae9756c
--- /dev/null
+++ b/examples/declarative/listview/recipes.qml
@@ -0,0 +1,133 @@
+import "content"
+// This example illustrates expanding a list item to show a more detailed view
+Rect {
+ id: page
+ width: 400; height: 240; 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
+ width: List.width
+ // 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.
+ property real detailsOpacity : 0
+
+ // 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.
+ HorizontalLayout {
+ id: topLayout
+ x: 10; y: 10; height: recipePic.height; width: parent.width
+ spacing: 10
+ Image {
+ id: recipePic
+ source: picture; width: 48; height: 48
+ }
+ VerticalLayout {
+ height: recipePic.height; width: background.width-recipePic.width-20
+ spacing: 5
+ Text { id: name; text: title; font.bold: true; font.size: 16 }
+ Text {
+ text: "Ingredients"; font.size: 12; font.bold: true
+ opacity: wrapper.detailsOpacity
+ }
+ Text {
+ text: ingredients; wrap: true; width: parent.width
+ opacity: wrapper.detailsOpacity
+ }
+ }
+ }
+ Item {
+ id: details
+ x: 10; width: parent.width-20
+ anchors.top: topLayout.bottom; anchors.topMargin: 10
+ anchors.bottom: parent.bottom; anchors.bottomMargin: 10
+ opacity: wrapper.detailsOpacity
+ Text {
+ id: methodTitle
+ text: "Method"; font.size: 12; font.bold: true
+ anchors.top: parent.top
+ }
+ Flickable {
+ id: flick
+ anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom
+ width: parent.width; viewportHeight: methodText.height; clip: true
+ Text { id: methodText; text: method; wrap: true; width: details.width }
+ }
+ Image {
+ anchors.right: flick.right; anchors.top: flick.top
+ source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1
+ }
+ Image {
+ anchors.right: flick.right; anchors.bottom: flick.bottom
+ source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1
+ }
+ }
+ // A button to close the detailed view, i.e. set the state back to default ('').
+ 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
+ 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 }
+ // 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 }
+ }
+ ]
+ transitions: [
+ Transition {
+ // Make the state changes smooth
+ ParallelAnimation {
+ ColorAnimation { duration: 500 }
+ NumericAnimation {
+ duration: 300; properties: "detailsOpacity,x,yPosition,height,width"
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ // The actual list
+ ListView {
+ id: List
+ model: Recipes; delegate: recipeDelegate
+ anchors.fill: parent; clip: true
+ }
+}
diff --git a/examples/declarative/listview/sections.qml b/examples/declarative/listview/sections.qml
new file mode 100644
index 0000000..60acd62
--- /dev/null
+++ b/examples/declarative/listview/sections.qml
@@ -0,0 +1,69 @@
+//! [0]
+Rect {
+ width: 200
+ height: 240
+ 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 that includes a separator for sections.
+ Component {
+ id: PetDelegate
+ Item {
+ id: Wrapper
+ width: 200
+ // My height is the combined height of the description and the section separator
+ height: Separator.height + Desc.height
+ Rect {
+ id: Separator
+ color: "lightsteelblue"
+ width: parent.width
+ // Only show the section separator when we are the beginning of a new section
+ // Note that for this to work nicely, the list must be ordered by section.
+ height: Wrapper.ListView.prevSection != Wrapper.ListView.section ? 20 : 0
+ opacity: Wrapper.ListView.prevSection != Wrapper.ListView.section ? 1 : 0
+ Text {
+ text: Wrapper.ListView.section; font.bold: true
+ x: 2; height: parent.height; vAlign: 'AlignVCenter'
+ }
+ }
+ Item {
+ id: Desc
+ x: 5
+ height: Layout.height + 4
+ anchors.top: Separator.bottom
+ VerticalLayout {
+ id: Layout
+ y: 2
+ Text { text: 'Name: ' + name }
+ Text { text: 'Type: ' + type }
+ Text { text: 'Age: ' + age }
+ }
+ }
+ }
+ }
+ // 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"
+ }
+ }
+ // The list
+ ListView {
+ id: List
+ width: 200
+ height: parent.height
+ model: MyPetsModel
+ delegate: PetDelegate
+ highlight: PetHighlight
+ // The sectionExpression is simply the size of the pet.
+ // We use this to determine which section we are in above.
+ sectionExpression: "size"
+ focus: true
+ }
+}
+//! [0]
diff --git a/examples/declarative/minehunt/Description.qml b/examples/declarative/minehunt/Description.qml
new file mode 100644
index 0000000..0241ae5
--- /dev/null
+++ b/examples/declarative/minehunt/Description.qml
@@ -0,0 +1,36 @@
+Item {
+ id: Page
+ height: MyText.height + 20
+ property var text
+ 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
+ }
+ }
+ filter: Shadow {
+ xOffset: 5
+ yOffset: 5
+ }
+}
diff --git a/examples/declarative/minehunt/Explosion.qml b/examples/declarative/minehunt/Explosion.qml
new file mode 100644
index 0000000..2886559
--- /dev/null
+++ b/examples/declarative/minehunt/Explosion.qml
@@ -0,0 +1,18 @@
+Item {
+ property bool explode : false
+
+ Particles {
+ width: 38
+ height: 21
+ lifeSpan: 3600000
+ lifeSpanDeviation: 0
+ source: "pics/star.png"
+ count: 200
+ angle: 270
+ angleDeviation: 360
+ velocity: 100
+ velocityDeviation: 20
+ z: 100
+ emitting: explode
+ }
+}
diff --git a/examples/declarative/minehunt/main.cpp b/examples/declarative/minehunt/main.cpp
new file mode 100644
index 0000000..7f10757
--- /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 qml = file.readAll();
+ canvas->setQml(qml, 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..bf31c3d
--- /dev/null
+++ b/examples/declarative/minehunt/minehunt.qml
@@ -0,0 +1,160 @@
+Item {
+ id: field
+ width: 370
+ height: 480
+
+ property int clickx : 0
+ property int clicky : 0
+
+ resources: [
+ Component {
+ id: tile
+ Flipable {
+ id: flipable
+ width: 40
+ height: 40
+ axis: Axis {
+ startX: 20
+ startY: 20
+ endX: 20
+ endY: 0
+ }
+ front: Image {
+ source: "pics/front.png"
+ width: 40
+ height: 40
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/flag.png"
+ opacity: modelData.hasFlag
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+ }
+ back: Image {
+ source: "pics/back.png"
+ 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 && modelData.hint > 0
+ }
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/bomb.png"
+ opacity: modelData.hasMine
+ }
+ Explosion {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ explode: modelData.hasMine==true && modelData.flipped==true
+ }
+ }
+ states: [
+ State {
+ name: "back"
+ when: modelData.flipped == true
+ SetProperty {
+ target: flipable
+ property: "rotation"
+ value: 180
+ }
+ }
+ ]
+ 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 && modelData.flipped==true){ret*3;}else{ret;}} else {0}}
+ }
+ NumericAnimation {
+ easing: "easeInOutQuad"
+ properties: "rotation"
+ }
+ }
+ }
+ ]
+ 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(mouse.button==undefined || mouse.button==Qt.RightButton){flag(row,col);}else{flip(row,col);} }
+ }
+ }
+ }
+ ]
+ Image {
+ source: "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
+ }
+ }
+ }
+ Item {
+ id: gamedata
+ width: 370
+ height: 100
+ y: 380
+ Text {
+ color: "white"
+ font.size: 18
+ x: 20
+ y: 20
+ }
+ Image {
+ x: 100
+ y: 20
+ source: "pics/bomb-color.png"
+ }
+ Text {
+ x: 100
+ y: 60
+ color: "white"
+ text: numMines
+ }
+ Image {
+ x: 140
+ y: 20
+ source: "pics/flag-color.png"
+ }
+ Text {
+ x: 140
+ y: 60
+ color: "white"
+ text: numFlags
+ }
+ Image {
+ x: 280
+ y: 10
+ source: if(isPlaying==true){'pics/face-smile.png'}else{if(hasWon==true){'pics/face-smile-big.png'}else{'pics/face-sad.png'}}
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { reset() }
+ }
+ }
+ }
+}
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/back.png b/examples/declarative/minehunt/pics/back.png
new file mode 100644
index 0000000..f6b3f0b
--- /dev/null
+++ b/examples/declarative/minehunt/pics/back.png
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/face-sad.png b/examples/declarative/minehunt/pics/face-sad.png
new file mode 100644
index 0000000..cf00aaf
--- /dev/null
+++ b/examples/declarative/minehunt/pics/face-sad.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/face-smile-big.png b/examples/declarative/minehunt/pics/face-smile-big.png
new file mode 100644
index 0000000..f9c2335
--- /dev/null
+++ b/examples/declarative/minehunt/pics/face-smile-big.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/face-smile.png b/examples/declarative/minehunt/pics/face-smile.png
new file mode 100644
index 0000000..3d66d72
--- /dev/null
+++ b/examples/declarative/minehunt/pics/face-smile.png
Binary files differ
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/front.png b/examples/declarative/minehunt/pics/front.png
new file mode 100644
index 0000000..834331b
--- /dev/null
+++ b/examples/declarative/minehunt/pics/front.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..471874d
--- /dev/null
+++ b/examples/declarative/mouseregion/mouse.qml
@@ -0,0 +1,38 @@
+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: ' + mouse.x + ' y: ' + mouse.y + ' button: ' + (mouse.button == Qt.RightButton ? 'right' : 'left') + ' Shift: ' + (mouse.modifiers & Qt.ShiftModifier ? 'true' : 'false') + ')') }
+ onReleased: { print('release (x: ' + mouse.x + ' y: ' + mouse.y + ' isClick: ' + mouse.isClick + ' wasHeld: ' + mouse.wasHeld + ')') }
+ onClicked: { print('click (x: ' + mouse.x + ' y: ' + mouse.y + ' wasHeld: ' + mouse.wasHeld + ')') }
+ onDoubleClicked: { print('double click (x: ' + mouse.x + ' y: ' + mouse.y + ')') }
+ onPressAndHold: { print('press and hold') }
+ onExitedWhilePressed: { print('exiting while pressed') }
+ onReenteredWhilePressed: { print('reentering while pressed') }
+ anchors.fill: parent
+ }
+ }
+ 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: ' + mouse.isClick + ') (wasHeld: ' + mouse.wasHeld + ')') }
+ onClicked: { print('click' + '(wasHeld: ' + mouse.wasHeld + ')') }
+ onDoubleClicked: { print('double click') }
+ onPressAndHold: { print('press and hold') }
+ onExitedWhilePressed: { print('exiting while pressed') }
+ onReenteredWhilePressed: { print('reentering while pressed') }
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/examples/declarative/scrollbar/ScrollBar.qml b/examples/declarative/scrollbar/ScrollBar.qml
new file mode 100644
index 0000000..8020d62
--- /dev/null
+++ b/examples/declarative/scrollbar/ScrollBar.qml
@@ -0,0 +1,29 @@
+Item {
+ id: ScrollBar
+ // The properties that define the scrollbar's state.
+ // position and pageSize are in the range 0.0 - 1.0. They are relative to the
+ // height of the page, i.e. a pageSize of 0.5 means that you can see 50%
+ // of the height of the view.
+ // orientation can be either 'Vertical' or 'Horizontal'
+ property var position
+ property var pageSize
+ property var orientation : "Vertical"
+
+ // 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)
+ }
+}
diff --git a/examples/declarative/scrollbar/display.qml b/examples/declarative/scrollbar/display.qml
new file mode 100644
index 0000000..42e8f25
--- /dev/null
+++ b/examples/declarative/scrollbar/display.qml
@@ -0,0 +1,63 @@
+Rect {
+ width: 640
+ height: 480
+ // Create a flickable to view a large image.
+ Flickable {
+ id: View
+ anchors.fill: parent
+ Image {
+ id: Picture
+ source: "pics/niagara_falls.jpg"
+ }
+ viewportWidth: Picture.width
+ viewportHeight: Picture.height
+ // 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "*"
+ NumericAnimation {
+ properties: "opacity"
+ duration: 400
+ }
+ }
+ ]
+ }
+ // 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
+ }
+}
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..8bc88e4
--- /dev/null
+++ b/examples/declarative/slideswitch/Switch.qml
@@ -0,0 +1,56 @@
+Item {
+ id: Switch
+ width: Groove.width; height: Groove.height
+
+ property var on
+
+ Script {
+
+ function toggle() {
+ if(Switch.state == "On")
+ Switch.state = "Off";
+ else
+ Switch.state = "On";
+ }
+ function dorelease() {
+ if(Knob.x == 1) {
+ if(Switch.state == "Off")
+ return;
+ }
+
+ if(Knob.x == 78) {
+ if(Switch.state == "On")
+ return;
+ }
+
+ toggle();
+ }
+
+ }
+ Image { id: Groove; source: "background.svg" }
+ MouseRegion { anchors.fill: Groove; onClicked: { toggle() } }
+ Image { id: Knob; source: "knob.svg"; x: 1; y: 2 }
+ MouseRegion {
+ anchors.fill: Knob
+ onClicked: { toggle() }
+ onReleased: { 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 {
+ name: "Off"
+ SetProperty { target: Knob; property: "x"; value: 1 }
+ SetProperty { target: Switch; property: "on"; value: false }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation { properties: "x"; easing: "easeInOutQuad"; duration: 200 }
+ }
+ ]
+}
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..cea89b6
--- /dev/null
+++ b/examples/declarative/slideswitch/display.qml
@@ -0,0 +1,8 @@
+Rect {
+ color: "white"
+ width: 150
+ height: 150
+ Switch {
+ anchors.centeredIn: parent
+ }
+}
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..bcde20c
--- /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 {
+ x: 0; y: 0; width: 50; height: 50
+ color: "transparent"; pen.color: "black"
+ MouseRegion { anchors.fill: parent; onClicked: { Page.state='' } }
+ }
+ // Another target region. Clicking in here sets the state to 'Position1'
+ Rect {
+ x: 150; y: 50; width: 50; height: 50
+ color: "transparent"; pen.color: "black"
+ MouseRegion { anchors.fill: parent; onClicked: { Page.state='Position1' } }
+ }
+ // Another target region. Clicking in here sets the state to 'Position2'
+ Rect {
+ x: 0; y: 200; width: 50; height: 50
+ color: "transparent"; pen.color: "black"
+ MouseRegion { anchors.fill: parent; onClicked: { Page.state='Position2' } }
+ }
+ // 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 }
+ },
+ // 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 }
+ }
+ ]
+}
diff --git a/examples/declarative/states/transitions.qml b/examples/declarative/states/transitions.qml
new file mode 100644
index 0000000..4c1dceb
--- /dev/null
+++ b/examples/declarative/states/transitions.qml
@@ -0,0 +1,60 @@
+Rect {
+ id: Page
+ width: 300; height: 300; color: "white"
+ // A target region. Clicking in here sets the state to '' - the default state
+ Rect {
+ x: 0; y: 0; width: 50; height: 50
+ color: "transparent"; pen.color: "black"
+ MouseRegion { anchors.fill: parent; onClicked: { Page.state='' } }
+ }
+ // Another target region. Clicking in here sets the state to 'Position1'
+ Rect {
+ x: 150; y: 50; width: 50; height: 50
+ color: "transparent"; pen.color: "black"
+ MouseRegion { anchors.fill: parent; onClicked: { Page.state='Position1' } }
+ }
+ // Another target region. Clicking in here sets the state to 'Position2'
+ Rect {
+ x: 0; y: 200; width: 50; height: 50
+ color: "transparent"; pen.color: "black"
+ MouseRegion { anchors.fill: parent; onClicked: { Page.state='Position2' } }
+ }
+ // 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 }
+ },
+ // 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 }
+ }
+ ]
+
+ // 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 }
+ },
+ // 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 }
+ },
+ // For any other state changes move x,y linearly over duration of 200ms.
+ Transition {
+ NumericAnimation { properties: "x,y"; duration: 200 }
+ }
+ ]
+}
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/Removebutton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/Removebutton.qml
new file mode 100644
index 0000000..bbe9f55
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/Removebutton.qml
@@ -0,0 +1,9 @@
+//! [0]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml
new file mode 100644
index 0000000..cc5ebae
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml
@@ -0,0 +1,34 @@
+Rect {
+ id: page
+ width: layout.width
+ height: layout.height
+ color: "white"
+ VerticalLayout {
+ id: layout
+ width: contents.width
+ GroupBox {
+ contents: "1/RemoveButton.qml"
+ label: "Rectangle Component"
+ }
+ GroupBox {
+ contents: "2/RemoveButton.qml"
+ label: "Closed Remove Item Button"
+ }
+ GroupBox {
+ contents: "2a/RemoveButton.qml"
+ label: "Alternative Closed Button"
+ }
+ GroupBox {
+ contents: "3/RemoveButton.qml"
+ label: "Open Remove Item Button"
+ }
+ GroupBox {
+ contents: "4/RemoveButton.qml"
+ label: "State Based Button"
+ }
+ GroupBox {
+ contents: "5/RemoveButton.qml"
+ label: "Animated Button"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml
new file mode 100644
index 0000000..247e38b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml
@@ -0,0 +1,18 @@
+//! [0]
+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
+ source: "../../shared/pics/trash.png"
+ }
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml
new file mode 100644
index 0000000..6c6a949
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml
@@ -0,0 +1,20 @@
+//! [0]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ children: [
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ }
+ ]
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml
new file mode 100644
index 0000000..3c20462
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml
@@ -0,0 +1,39 @@
+//! [0]
+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
+ source: "../../shared/pics/cancel.png"
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../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"
+ }
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml
new file mode 100644
index 0000000..a359aaf
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml
@@ -0,0 +1,110 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+//! [script]
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+//! [script]
+//! [mouse region]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+//! [mouse region]
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ 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]
+ 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
+ }
+ }
+ ]
+//! [states]
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml
new file mode 100644
index 0000000..4db49ea
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml
@@ -0,0 +1,117 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+//! [script]
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+//! [script]
+//! [mouse region]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ id: trashMouseRegion
+ anchors.fill: parent
+ }
+ Connection {
+ sender: trashMouseRegion
+ signal: clicked()
+ script: {
+ toggle()
+ }
+ }
+ }
+//! [mouse region]
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ 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]
+ 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
+ }
+ }
+ ]
+//! [states]
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml
new file mode 100644
index 0000000..29d464b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml
@@ -0,0 +1,117 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+//! [transition]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+//! [transition]
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml
new file mode 100644
index 0000000..edaae72
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml
@@ -0,0 +1,57 @@
+FocusRealm {
+ id: groupBox
+ width: Math.max(270, subItem.width+40)
+ height: Math.max(70, subItem.height+40)
+
+ property var contents
+ property var label
+
+ Rect {
+ id: wrapper
+ x: 5
+ y: 10
+ radius: 10
+ width: groupBox.width-20
+ height: groupBox.height-20
+ color: "white"
+ pen.color: "black"
+ Item {
+ id: subItem
+ qml: groupBox.contents
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ width: qmlItem.width
+ height: qmlItem.height
+ }
+ }
+ Rect {
+ x: 20
+ y: 0
+ height: text.height
+ width: text.width+10
+ color: "white"
+ Text {
+ x: 5
+ id: text
+ text: label
+ font.bold: true
+ }
+ }
+ Rect {
+ color: "black"
+ anchors.fill: parent
+ opacity: parent.focus ? 0 : 0.3
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { parent.parent.focus=true }
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml
new file mode 100644
index 0000000..0218c3d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml
@@ -0,0 +1,30 @@
+//! [load]
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ }
+//! [load]
+ Text {
+ id: fieldText
+ width: contactField.width-80
+ anchors.right: removeButton.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ font.bold: true
+ color: "black"
+ text: 123123
+ }
+ Image {
+ source: "../../shared/pics/phone.png"
+ anchors.right: fieldText.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml
new file mode 100644
index 0000000..3142c45
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml
@@ -0,0 +1,115 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml
new file mode 100644
index 0000000..62089b8
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml
@@ -0,0 +1,33 @@
+//! [load]
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+ Item {
+ id: removeButton
+ qml: "RemoveButton.qml"
+ width: qmlItem.width
+ height: qmlItem.height
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ }
+//! [load]
+ Text {
+ id: fieldText
+ width: contactField.width-80
+ anchors.right: removeButton.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ font.bold: true
+ color: "black"
+ text: 123123
+ }
+ Image {
+ source: "../../shared/pics/phone.png"
+ anchors.right: fieldText.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml
new file mode 100644
index 0000000..3142c45
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml
@@ -0,0 +1,115 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml b/examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml
new file mode 100644
index 0000000..92893f6
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml
@@ -0,0 +1,33 @@
+//! [all]
+Rect {
+ width: 100
+ height: 100
+ color: "blue"
+ resources: [
+ Component {
+ id: redRectangle
+ Rect {
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ }
+ }
+ ]
+ ComponentInstance {
+ component: redRectangle
+ anchors.right: parent.right
+ anchors.top: parent.top
+ }
+ ComponentInstance {
+ component: redRectangle
+ anchors.left: parent.left
+ anchors.top: parent.top
+ }
+ ComponentInstance {
+ component: redRectangle
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ }
+}
+//! [all]
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml
new file mode 100644
index 0000000..bf6e82d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml
@@ -0,0 +1,117 @@
+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';
+ }
+ }
+
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml
new file mode 100644
index 0000000..2542c1c
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml
@@ -0,0 +1,32 @@
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+//! [use properties and signals]
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { fieldText.text='' }
+ }
+//! [use properties and signals]
+ Text {
+ id: fieldText
+ width: contactField.width-80
+ anchors.right: removeButton.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ font.bold: true
+ color: "black"
+ text: 123123
+ }
+ Image {
+ source: "../../shared/pics/phone.png"
+ anchors.right: fieldText.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml
new file mode 100644
index 0000000..99a521d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml
@@ -0,0 +1,123 @@
+//! [define properties and signals]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+//! [define properties and signals]
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+//! [use signal]
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle(); removeButton.confirmed.emit() }
+ }
+//! [use signal]
+ }
+ 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"
+//! [use width]
+ SetProperty {
+ target: removeButton
+ property: "width"
+ value: removeButton.expandedWidth
+ }
+//! [use width]
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
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..6ad2eb5
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml
@@ -0,0 +1,37 @@
+Rect {
+ id: page
+ width: layout.width
+ height: layout.height
+ color: "white"
+ GridLayout {
+ id: layout
+ columns: 2
+ rows: 4
+ width: contents.width
+ GroupBox {
+ contents: "1/ContactField.qml"
+ label: "Loading: simple"
+ }
+ GroupBox {
+ contents: "1a/ContactField.qml"
+ label: "Loading: qml property"
+ }
+ GroupBox {
+ contents: "2/ContactField.qml"
+ label: "Using properties"
+ }
+ GroupBox {
+ id: prev
+ contents: "3/ContactField.qml"
+ label: "Defining signals"
+ }
+ GroupBox {
+ contents: "3/Contact.qml"
+ label: "Multiple Items"
+ }
+ GroupBox {
+ contents: "4/Contact.qml"
+ label: "Mouse Grabbing"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml
new file mode 100644
index 0000000..763a771
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml
@@ -0,0 +1,47 @@
+Item {
+ id: contactDetails
+ width: 230
+ height: layout.height
+
+ property var contactId: ""
+ property var label: ""
+ property var phone: ""
+ property var email: ""
+
+ onLabelChanged: { labelField.value = label }
+ onEmailChanged: { emailField.value = email }
+ onPhoneChanged: { phoneField.value = phone }
+
+ 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"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml
new file mode 100644
index 0000000..890d781
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml
@@ -0,0 +1,61 @@
+//! [all]
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+ property var label: "Name"
+ property var icon: "../../shared/pics/phone.png"
+ property var value: ""
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { 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
+ source: 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "width,rightMargin"
+ duration: 200
+ }
+ }
+ ]
+}
+//! [all]
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml
new file mode 100644
index 0000000..f6cc1e4
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml
@@ -0,0 +1,148 @@
+//! [value change]
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "white"
+ property var text: ""
+ onTextChanged: { reset() }
+//! [value change]
+ property var label: ""
+ signal confirmed
+ 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='';
+ }
+
+ }
+ ]
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ }
+ TextEdit {
+ id: textEdit
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ font.bold: true
+ readOnly: true
+ wrap: false
+ }
+//! [behavior]
+ 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 == '' ? 1 : 0
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+//! [behavior]
+ 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: 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: 39
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "rightMargin"
+ value: 39
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml
new file mode 100644
index 0000000..2f27a69
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml
@@ -0,0 +1,119 @@
+//! [all]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle(); removeButton.confirmed.emit() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
+//! [all]
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml
new file mode 100644
index 0000000..bcb242f
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml
@@ -0,0 +1,50 @@
+//! [grab property]
+Item {
+ id: contactDetails
+ width: 230
+ height: layout.height
+ property var mouseGrabbed: false
+//! [grab property]
+
+ property var contactId: ""
+ property var label: ""
+ property var phone: ""
+ property var email: ""
+
+ onLabelChanged: { labelField.value = label }
+ onEmailChanged: { emailField.value = email }
+ onPhoneChanged: { phoneField.value = phone }
+
+ 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"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml
new file mode 100644
index 0000000..e9927e9
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml
@@ -0,0 +1,58 @@
+Item {
+ id: contactField
+ clip: true
+ height: 30
+ property var label: "Name"
+ property var icon: "../../shared/pics/phone.png"
+ property var value: ""
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { 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
+ source: 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "width,rightMargin"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml
new file mode 100644
index 0000000..e969f7b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml
@@ -0,0 +1,149 @@
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "white"
+ property var text: ""
+ property var label: ""
+ onTextChanged: { reset() }
+ signal confirmed
+ resources: [
+ Script {
+
+ function edit() {
+ if (!contactDetails.mouseGrabbed) {
+ fieldText.state='editing';
+ contactDetails.mouseGrabbed=true;
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ contactDetails.mouseGrabbed=false;
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ contactDetails.mouseGrabbed=false;
+ }
+
+ }
+ ]
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ }
+ TextEdit {
+ id: textEdit
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ 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 == '' ? 1 : 0
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+ 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: 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: 39
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "rightMargin"
+ value: 39
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml
new file mode 100644
index 0000000..bfe496e
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml
@@ -0,0 +1,123 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+ resources: [
+//! [grab]
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ contactDetails.mouseGrabbed=false;
+ } else {
+ if (!contactDetails.mouseGrabbed) {
+ removeButton.state = 'opened';
+ contactDetails.mouseGrabbed=true;
+ }
+ }
+ }
+
+ }
+//! [grab]
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle(); removeButton.confirmed.emit() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml b/examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml
new file mode 100644
index 0000000..edaae72
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml
@@ -0,0 +1,57 @@
+FocusRealm {
+ id: groupBox
+ width: Math.max(270, subItem.width+40)
+ height: Math.max(70, subItem.height+40)
+
+ property var contents
+ property var label
+
+ Rect {
+ id: wrapper
+ x: 5
+ y: 10
+ radius: 10
+ width: groupBox.width-20
+ height: groupBox.height-20
+ color: "white"
+ pen.color: "black"
+ Item {
+ id: subItem
+ qml: groupBox.contents
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ width: qmlItem.width
+ height: qmlItem.height
+ }
+ }
+ Rect {
+ x: 20
+ y: 0
+ height: text.height
+ width: text.width+10
+ color: "white"
+ Text {
+ x: 5
+ id: text
+ text: label
+ font.bold: true
+ }
+ }
+ Rect {
+ color: "black"
+ anchors.fill: parent
+ opacity: parent.focus ? 0 : 0.3
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { parent.parent.focus=true }
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml b/examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml
new file mode 100644
index 0000000..5400544
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml
@@ -0,0 +1,44 @@
+import "../lib"
+Item {
+ id: contacts
+ width: 240
+ height: 230
+ property var mouseGrabbed: false
+ resources: [
+//! [model]
+ 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"
+ }
+//! [model]
+ ]
+//! [view]
+ ListView {
+ id: contactListView
+ anchors.fill: parent
+ clip: true
+ model: contactList
+ focus: true
+//! [delegate]
+ delegate: [
+ Text {
+ x: 45
+ y: 12
+ width: contactListView.width-45
+ height: 30
+ color: "black"
+ font.bold: true
+ text: model.label
+ }
+ ]
+//! [delegate]
+ }
+//! [view]
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml b/examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml
new file mode 100644
index 0000000..0a293f5
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml
@@ -0,0 +1,126 @@
+import "../lib"
+Item {
+ id: contacts
+ width: 240
+ height: 230
+ property var mouseGrabbed: false
+ 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"
+ }
+ ]
+//! [button]
+ Button {
+ id: cancelEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "../../shared/pics/cancel.png"
+ opacity: mouseGrabbed ? 0 : 1
+ }
+//! [button]
+ ListView {
+ id: contactListView
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: cancelEditButton.bottom
+ anchors.bottom: parent.bottom
+ clip: true
+ model: contactList
+ focus: true
+ delegate: [
+//! [components]
+ Item {
+ id: wrapper
+ x: 0
+ width: ListView.view.width
+ height: 34
+ Text {
+ id: label
+ x: 45
+ y: 12
+ width: parent.width-45
+ color: "black"
+ font.bold: true
+ text: model.label
+ }
+ MouseRegion {
+ anchors.fill: label
+ onClicked: { wrapper.state='opened'; }
+ }
+ Contact {
+ id: Details
+ anchors.fill: parent
+ contactId: model.recid
+ label: model.label
+ email: model.email
+ phone: model.phone
+ opacity: 0
+ }
+//! [components]
+//! [states]
+ 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
+ }
+ }
+ ]
+//! [states]
+//! [transitions]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ duration: 500
+ properties: "yPosition,height,opacity"
+ }
+ }
+ ]
+//! [transitions]
+//! [connections]
+ Connection {
+ sender: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened') {
+ wrapper.state = '';
+ }
+ }
+ }
+//! [connections]
+ }
+ ]
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml b/examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml
new file mode 100644
index 0000000..7a44a3f
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml
@@ -0,0 +1,139 @@
+import "../lib"
+Item {
+ id: contacts
+ width: 240
+ height: 230
+ property var mouseGrabbed: false
+ 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"
+ }
+ ]
+ Button {
+ id: cancelEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "../../shared/pics/cancel.png"
+ opacity: mouseGrabbed ? 0 : 1
+ }
+ ListView {
+ id: contactListView
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: cancelEditButton.bottom
+ anchors.bottom: parent.bottom
+ clip: true
+ model: contactList
+ focus: true
+ delegate: [
+ Item {
+ id: wrapper
+ x: 0
+ width: ListView.view.width
+ height: 34
+ Text {
+ id: label
+ x: 45
+ y: 12
+ width: parent.width-45
+ color: "black"
+ font.bold: true
+ text: model.label
+ }
+//! [setting qml]
+ MouseRegion {
+ anchors.fill: label
+ onClicked: {
+ Details.qml = 'Contact.qml';
+ wrapper.state='opened';
+ }
+ }
+ Item {
+ id: Details
+ anchors.fill: parent
+ opacity: 0
+//! [setting qml]
+//! [binding]
+ Bind {
+ target: Details.qmlItem
+ property: "contactId"
+ value: model.recid
+ }
+ 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
+ }
+//! [binding]
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ duration: 500
+ properties: "yPosition,height,opacity"
+ }
+ }
+ ]
+ Connection {
+ sender: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened') {
+ wrapper.state = '';
+ }
+ }
+ }
+ }
+ ]
+ }
+}
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..7d9937c
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml
@@ -0,0 +1,29 @@
+Rect {
+ id: page
+ width: layout.width
+ height: layout.height
+ color: "white"
+ Bind {
+ id: currentItem
+ value: true
+ }
+ // relies on the current focus behavior whereby setting focus=true on a
+ // component removes focus from any previous element
+ GridLayout {
+ id: layout
+ width: contents.width
+ height: contents.height
+ GroupBox {
+ contents: "1/ContactView.qml"
+ label: "list only"
+ }
+ GroupBox {
+ contents: "2/ContactView.qml"
+ label: "dynamic delegate"
+ }
+ GroupBox {
+ contents: "3/ContactView.qml"
+ label: "delayed loading"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml b/examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml
new file mode 100644
index 0000000..edaae72
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml
@@ -0,0 +1,57 @@
+FocusRealm {
+ id: groupBox
+ width: Math.max(270, subItem.width+40)
+ height: Math.max(70, subItem.height+40)
+
+ property var contents
+ property var label
+
+ Rect {
+ id: wrapper
+ x: 5
+ y: 10
+ radius: 10
+ width: groupBox.width-20
+ height: groupBox.height-20
+ color: "white"
+ pen.color: "black"
+ Item {
+ id: subItem
+ qml: groupBox.contents
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ width: qmlItem.width
+ height: qmlItem.height
+ }
+ }
+ Rect {
+ x: 20
+ y: 0
+ height: text.height
+ width: text.width+10
+ color: "white"
+ Text {
+ x: 5
+ id: text
+ text: label
+ font.bold: true
+ }
+ }
+ Rect {
+ color: "black"
+ anchors.fill: parent
+ opacity: parent.focus ? 0 : 0.3
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { parent.parent.focus=true }
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/Button.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/Button.qml
new file mode 100644
index 0000000..d9f1236
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/Button.qml
@@ -0,0 +1,57 @@
+Item {
+ id: button
+ width: 30
+ height: 30
+ property var icon: ""
+ signal clicked
+ Rect {
+ id: buttonRect
+ anchors.fill: parent
+ color: "lightgreen"
+ radius: 5
+ Image {
+ id: iconImage
+ source: 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"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "pressed"
+ ColorAnimation {
+ duration: 200
+ }
+ },
+ Transition {
+ fromState: "pressed"
+ toState: "*"
+ ColorAnimation {
+ duration: 1000
+ }
+ }
+ ]
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml
new file mode 100644
index 0000000..6832076
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml
@@ -0,0 +1,46 @@
+Item {
+ id: contactDetails
+ anchors.fill: parent
+
+ property var contactId: ""
+ property var label: ""
+ property var phone: ""
+ property var email: ""
+
+ onLabelChanged: { labelField.value = label }
+ onEmailChanged: { emailField.value = email }
+ onPhoneChanged: { phoneField.value = phone }
+
+ 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"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml
new file mode 100644
index 0000000..e9927e9
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml
@@ -0,0 +1,58 @@
+Item {
+ id: contactField
+ clip: true
+ height: 30
+ property var label: "Name"
+ property var icon: "../../shared/pics/phone.png"
+ property var value: ""
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { 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
+ source: 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "width,rightMargin"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml
new file mode 100644
index 0000000..427e2b0
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml
@@ -0,0 +1,149 @@
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "white"
+ property var text: ""
+ property var label: ""
+ onTextChanged: { reset() }
+ signal confirmed
+ resources: [
+ Script {
+
+ function edit() {
+ if (!contacts.mouseGrabbed) {
+ fieldText.state='editing';
+ contacts.mouseGrabbed=true;
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ }
+
+ }
+ ]
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ }
+ TextEdit {
+ id: textEdit
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ 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 == '' ? 1 : 0
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+ 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: 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: 39
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "rightMargin"
+ value: 39
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml
new file mode 100644
index 0000000..c0ea79d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml
@@ -0,0 +1,121 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ contacts.mouseGrabbed=false;
+ } else {
+ if (!contacts.mouseGrabbed) {
+ removeButton.state = 'opened';
+ contacts.mouseGrabbed=true;
+ }
+ }
+ }
+
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle(); removeButton.confirmed.emit() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/shared/contactGenSQL.pl b/examples/declarative/tutorials/contacts/shared/contactGenSQL.pl
new file mode 100755
index 0000000..2d328da
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/contactGenSQL.pl
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+my $count = shift;
+
+open(MFIRST, "<english-m.txt") or die "Could not open male names";
+open(FFIRST, "<english-f.txt") or die "Could not open female names";
+open(SURNAME, "<english-s.txt") or die "Could not open surnames names";
+open(ISP, "<email.txt") or die "Could not open isp names";
+
+my @mnames = <MFIRST>;
+my @fnames = <FFIRST>;
+my @surnames = <SURNAME>;
+my @isps = <ISP>;
+
+print "BEGIN;\n";
+print "CREATE TABLE contacts (recid INTEGER PRIMARY KEY, label TEXT, phone TEXT, email TEXT);\n";
+print "CREATE INDEX contactSortOrder ON contacts(label, recid);\n";
+
+my $i = 0;
+while ($i < $count) {
+ $i++;
+ my $fn = randomFirstName();
+ my $sn = randomLastName();
+ my $em = randomEmail($fn, $sn);
+ my $ph = randomPhoneNumber();
+
+ $fn =~ s/'/''/g;
+ $sn =~ s/'/''/g;
+ $em =~ s/'/''/g;
+ print "INSERT INTO contacts (label, email, phone) VALUES('$fn $sn', '$em', '$ph');\n"
+}
+
+print "COMMIT;\n";
+
+
+sub randomFirstName
+{
+ my $name;
+ if (int(rand 2) == 1) {
+ $name = $mnames[int(rand @mnames)];
+ } else {
+ $name = $fnames[int(rand @fnames)];
+ }
+ chomp $name;
+ $name;
+}
+
+sub randomLastName
+{
+ my $name = $surnames[int(rand @surnames)];
+ chomp $name;
+ $name;
+}
+
+sub randomEmail
+{
+ my ($fn, $ln) = @_;
+ my $isp = $isps[int(rand @isps)];
+ chomp $isp;
+ my $path = int(rand 3);
+ my $email;
+ if ($path == 0) {
+ $email = "$fn.$ln\@$isp";
+ } elsif ($path == 1) {
+ $email = "$fn\@$isp";
+ } elsif ($path == 2) {
+ $email = "$ln\@$isp";
+ }
+}
+
+sub randomPhoneNumber
+{
+ my @digits = qw(1 2 3 4 5 6 7 8 9 0);
+ my $phonenumber;
+ for (1 .. 8) {
+ $phonenumber .= $digits[int(rand @digits)];
+ }
+ $phonenumber;
+}
diff --git a/examples/declarative/tutorials/contacts/shared/contacts.sqlite b/examples/declarative/tutorials/contacts/shared/contacts.sqlite
new file mode 100644
index 0000000..d903775
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/contacts.sqlite
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/email.txt b/examples/declarative/tutorials/contacts/shared/email.txt
new file mode 100644
index 0000000..de9894b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/email.txt
@@ -0,0 +1,7 @@
+emails.com
+emails.net
+mailserver.org
+mailserver.net
+mailserver.com
+BobsMail.com
+BillMail.com
diff --git a/examples/declarative/tutorials/contacts/shared/english-f.txt b/examples/declarative/tutorials/contacts/shared/english-f.txt
new file mode 100644
index 0000000..7da5474
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/english-f.txt
@@ -0,0 +1,143 @@
+Aimee
+Aleksandra
+Alice
+Alicia
+Allison
+Alyssa
+Amy
+Andrea
+Angel
+Angela
+Ann
+Anna
+Anne
+Anne
+Marie
+Annie
+Ashley
+Barbara
+Beatrice
+Beth
+Betty
+Brenda
+Brooke
+Candace
+Cara
+Caren
+Carol
+Caroline
+Carolyn
+Carrie
+Cassandra
+Catherine
+Charlotte
+Chrissy
+Christen
+Christina
+Christine
+Christy
+Claire
+Claudia
+Courtney
+Crystal
+Cynthia
+Dana
+Danielle
+Deanne
+Deborah
+Deirdre
+Denise
+Diane
+Dianne
+Dorothy
+Eileen
+Elena
+Elizabeth
+Emily
+Erica
+Erin
+Frances
+Gina
+Giulietta
+Heather
+Helen
+Jane
+Janet
+Janice
+Jenna
+Jennifer
+Jessica
+Joanna
+Joyce
+Julia
+Juliana
+Julie
+Justine
+Kara
+Karen
+Katharine
+Katherine
+Kathleen
+Kathryn
+Katrina
+Kelly
+Kerry
+Kim
+Kimberly
+Kristen
+Kristina
+Kristine
+Laura
+Laurel
+Lauren
+Laurie
+Leah
+Linda
+Lisa
+Lori
+Marcia
+Margaret
+Maria
+Marina
+Marisa
+Martha
+Mary
+Mary
+Ann
+Maya
+Melanie
+Melissa
+Michelle
+Monica
+Nancy
+Natalie
+Nicole
+Nina
+Pamela
+Patricia
+Rachel
+Rebecca
+Renee
+Sandra
+Sara
+Sharon
+Sheri
+Shirley
+Sonia
+Stefanie
+Stephanie
+Susan
+Suzanne
+Sylvia
+Tamara
+Tara
+Tatiana
+Terri
+Theresa
+Tiffany
+Tracy
+Valerie
+Veronica
+Vicky
+Vivian
+Wendy
diff --git a/examples/declarative/tutorials/contacts/shared/english-m.txt b/examples/declarative/tutorials/contacts/shared/english-m.txt
new file mode 100644
index 0000000..3c7b13e
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/english-m.txt
@@ -0,0 +1,130 @@
+Aaron
+Adam
+Adrian
+Alan
+Alejandro
+Alex
+Allen
+Andrew
+Andy
+Anthony
+Art
+Arthur
+Barry
+Bart
+Ben
+Benjamin
+Bill
+Bobby
+Brad
+Bradley
+Brendan
+Brett
+Brian
+Bruce
+Bryan
+Carlos
+Chad
+Charles
+Chris
+Christopher
+Chuck
+Clay
+Corey
+Craig
+Dan
+Daniel
+Darren
+Dave
+David
+Dean
+Dennis
+Denny
+Derek
+Don
+Doug
+Duane
+Edward
+Eric
+Eugene
+Evan
+Frank
+Fred
+Gary
+Gene
+George
+Gordon
+Greg
+Harry
+Henry
+Hunter
+Ivan
+Jack
+James
+Jamie
+Jason
+Jay
+Jeff
+Jeffrey
+Jeremy
+Jim
+Joe
+Joel
+John
+Jonathan
+Joseph
+Justin
+Keith
+Ken
+Kevin
+Larry
+Logan
+Marc
+Mark
+Matt
+Matthew
+Michael
+Mike
+Nat
+Nathan
+Patrick
+Paul
+Perry
+Peter
+Philip
+Phillip
+Randy
+Raymond
+Ricardo
+Richard
+Rick
+Rob
+Robert
+Rod
+Roger
+Ross
+Ruben
+Russell
+Ryan
+Sam
+Scot
+Scott
+Sean
+Shaun
+Stephen
+Steve
+Steven
+Stewart
+Stuart
+Ted
+Thomas
+Tim
+Toby
+Todd
+Tom
+Troy
+Victor
+Wade
+Walter
+Wayne
+William
diff --git a/examples/declarative/tutorials/contacts/shared/english-s.txt b/examples/declarative/tutorials/contacts/shared/english-s.txt
new file mode 100644
index 0000000..1f3682d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/english-s.txt
@@ -0,0 +1,1003 @@
+Adams
+Adamson
+Adler
+Akers
+Akin
+Aleman
+Alexander
+Allen
+Allison
+Allwood
+Anderson
+Andreou
+Anthony
+Appelbaum
+Applegate
+Arbore
+Arenson
+Armold
+Arntzen
+Askew
+Athanas
+Atkinson
+Ausman
+Austin
+Averitt
+Avila-Sakar
+Badders
+Baer
+Baggerly
+Bailliet
+Baird
+Baker
+Ball
+Ballentine
+Ballew
+Banks
+Baptist-Nguyen
+Barbee
+Barber
+Barchas
+Barcio
+Bardsley
+Barkauskas
+Barnes
+Barnett
+Barnwell
+Barrera
+Barreto
+Barroso
+Barrow
+Bart
+Barton
+Bass
+Bates
+Bavinger
+Baxter
+Bazaldua
+Becker
+Beeghly
+Belforte
+Bellamy
+Bellavance
+Beltran
+Belusar
+Bennett
+Benoit
+Bensley
+Berger
+Berggren
+Bergman
+Berry
+Bertelson
+Bess
+Beusse
+Bickford
+Bierner
+Bird
+Birdwell
+Bixby
+Blackmon
+Blackwell
+Blair
+Blankinship
+Blanton
+Block
+Blomkalns
+Bloomfield
+Blume
+Boeckenhauer
+Bolding
+Bolt
+Bolton
+Book
+Boucher
+Boudreau
+Bowman
+Boyd
+Boyes
+Boyles
+Braby
+Braden
+Bradley
+Brady
+Bragg
+Brandow
+Brantley
+Brauner
+Braunhardt
+Bray
+Bredenberg
+Bremer
+Breyer
+Bricout
+Briggs
+Brittain
+Brockman
+Brockmoller
+Broman
+Brooks
+Brown
+Brubaker
+Bruce
+Brumfield
+Brumley
+Bruning
+Buck
+Budd
+Buhler
+Buhr
+Burleson
+Burns
+Burton
+Bush
+Butterfield
+Byers
+Byon
+Byrd
+Bzostek
+Cabrera
+Caesar
+Caffey
+Caffrey
+Calhoun
+Call
+Callahan
+Campbell
+Cano
+Capri
+Carey
+Carlisle
+Carlson
+Carmichael
+Carnes
+Carr
+Carreira
+Carroll
+Carson
+Carswell
+Carter
+Cartwright
+Cason
+Cates
+Catlett
+Caudle
+Cavallaro
+Cave
+Cazamias
+Chabot
+Chance
+Chapman
+Characklis
+Cheatham
+Chen
+Chern
+Cheville
+Chong
+Christensen
+Church
+Claibourn
+Clark
+Clasen
+Claude
+Close
+Coakley
+Coffey
+Cohen
+Cole
+Collier
+Conant
+Connell
+Conte
+Conway
+Cooley
+Cooper
+Copeland
+Coram
+Corbett
+Cort
+Cortes
+Cousins
+Cowsar
+Cox
+Coyne
+Crain
+Crankshaw
+Craven
+Crawford
+Cressman
+Crestani
+Crier
+Crocker
+Cromwell
+Crouse
+Crowder
+Crowe
+Culpepper
+Cummings
+Cunningham
+Currie
+Cusey
+Cutcher
+Cyprus
+D'Ascenzo
+Dabak
+Dakoulas
+Daly
+Dana
+Danburg
+Danenhauer
+Darley
+Darrouzet
+Dartt
+Daugherty
+Davila
+Davis
+Dawkins
+Day
+DeHart
+DeMoss
+DeMuth
+DeVincentis
+Deaton
+Dees
+Degenhardt
+Deggeller
+Deigaard
+Delabroy
+Delaney
+Demir
+Denison
+Denney
+Derr
+Deuel
+Devitt
+Diamond
+Dickinson
+Dietrich
+Dilbeck
+Dobson
+Dodds
+Dodson
+Doherty
+Dooley
+Dorsey
+Dortch
+Doughty
+Dove
+Dowd
+Dowling
+Drescher
+Drucker
+Dryer
+Dryver
+Duckworth
+Dunbar
+Dunham
+Dunn
+Duston
+Dettweiler
+Dyson
+Eason
+Eaton
+Ebert
+Eckhoff
+Edelman
+Edmonds
+Eichhorn
+Eisbach
+Elders
+Elias
+Elijah
+Elizabeth
+Elliott
+Elliston
+Elms
+Emerson
+Engelberg
+Engle
+Eplett
+Epp
+Erickson
+Estades
+Etezadi
+Evans
+Ewing
+Fair
+Farfan
+Fargason
+Farhat
+Farry
+Fawcett
+Faye
+Federle
+Felcher
+Feldman
+Ferguson
+Fergusson
+Fernandez
+Ferrer
+Fine
+Fineman
+Fisher
+Flanagan
+Flathmann
+Fleming
+Fletcher
+Folk
+Fortune
+Fossati
+Foster
+Foulston
+Fowler
+Fox
+Francis
+Frantom
+Franz
+Frazer
+Fredericks
+Frey
+Freymann
+Fuentes
+Fuller
+Fundling
+Furlong
+Gainer
+Galang
+Galeazzi
+Gamse
+Gannaway
+Garcia
+Gardner
+Garneau
+Gartler
+Garverick
+Garza
+Gatt
+Gattis
+Gayman
+Geiger
+Gelder
+George
+Gerbino
+Gerbode
+Gibson
+Gifford
+Gillespie
+Gillingham
+Gilpin
+Gilyot
+Girgis
+Gjertsen
+Glantz
+Glaze
+Glenn
+Glotzbach
+Gobble
+Gockenbach
+Goff
+Goffin
+Golden
+Goldwyn
+Gomez
+Gonzalez
+Good
+Graham
+Gramm
+Granlund
+Grant
+Gray
+Grayson
+Greene
+Greenslade
+Greenwood
+Greer
+Griffin
+Grinstein
+Grisham
+Gross
+Grove
+Guthrie
+Guyton
+Haas
+Hackney
+Haddock
+Hagelstein
+Hagen
+Haggard
+Haines
+Hale
+Haley
+Hall
+Halladay
+Hamill
+Hamilton
+Hammer
+Hancock
+Hane
+Hansen
+Harding
+Harless
+Harms
+Harper
+Harrigan
+Harris
+Harrison
+Hart
+Harton
+Hartz
+Harvey
+Hastings
+Hauenstein
+Haushalter
+Haven
+Hawes
+Hawkins
+Hawley
+Haygood
+Haylock
+Hazard
+Heath
+Heidel
+Heins
+Hellums
+Hendricks
+Henry
+Henson
+Herbert
+Herman
+Hernandez
+Herrera
+Hertzmann
+Hewitt
+Hightower
+Hildebrand
+Hill
+Hindman
+Hirasaki
+Hirsh
+Hochman
+Hocker
+Hoffman
+Hoffmann
+Holder
+Holland
+Holloman
+Holstein
+Holt
+Holzer
+Honeyman
+Hood
+Hooks
+Hopper
+Horne
+House
+Houston
+Howard
+Howell
+Howley
+Huang
+Hudgings
+Huffman
+Hughes
+Humphrey
+Hunt
+Hunter
+Hurley
+Huston
+Hutchinson
+Hyatt
+Irving
+Jacobs
+Jaramillo
+Jaranson
+Jarboe
+Jarrell
+Jenkins
+Johnson
+Johnston
+Jones
+Joy
+Juette
+Julicher
+Jumper
+Kabir
+Kamberova
+Kamen
+Kamine
+Kampe
+Kane
+Kang
+Kapetanovic
+Kargatis
+Karlin
+Karlsson
+Kasbekar
+Kasper
+Kastensmidt
+Katz
+Kauffman
+Kavanagh
+Kaydos
+Kearsley
+Keleher
+Kelly
+Kelty
+Kendrick
+Key
+Kicinski
+Kiefer
+Kielt
+Kim
+Kimmel
+Kincaid
+King
+Kinney
+Kipp
+Kirby
+Kirk
+Kirkland
+Kirkpatrick
+Klamczynski
+Klein
+Kopnicky
+Kotsonis
+Koutras
+Kramer
+Kremer
+Krohn
+Kuhlken
+Kunitz
+LaLonde
+LaValle
+LaWare
+Lacy
+Lam
+Lamb
+Lampkin
+Lane
+Langston
+Lanier
+Larsen
+Lassiter
+Latchford
+Lawera
+LeBlanc
+LeGrand
+Leatherbury
+Lebron
+Ledman
+Lee
+Leinenbach
+Leslie
+Levy
+Lewis
+Lichtenstein
+Lisowski
+Liston
+Litvak
+Llano-Restrepo
+Lloyd
+Lock
+Lodge
+Logan
+Lomonaco
+Long
+Lopez
+Lopez-Bassols
+Loren
+Loughridge
+Love
+Ludtke
+Luers
+Lukes
+Luxemburg
+MacAllister
+MacLeod
+Mackey
+Maddox
+Magee
+Mallinson
+Mann
+Manning
+Manthos
+Marie
+Marrow
+Marshall
+Martin
+Martinez
+Martisek
+Massey
+Mathis
+Matt
+Maxwell
+Mayer
+Mazurek
+McAdams
+McAfee
+McAlexander
+McBride
+McCarthy
+McClure
+McCord
+McCoy
+McCrary
+McCrossin
+McDonald
+McElfresh
+McFarland
+McGarr
+McGhee
+McGoldrick
+McGrath
+McGuire
+McKinley
+McMahan
+McMahon
+McMath
+McNally
+Mcdonald
+Meade
+Meador
+Mebane
+Medrano
+Melton
+Merchant
+Merwin
+Millam
+Millard
+Miller
+Mills
+Milstead
+Minard
+Miner
+Minkoff
+Minnotte
+Minyard
+Mirza
+Mitchell
+Money
+Monk
+Montgomery
+Monton
+Moore
+Moren
+Moreno
+Morris
+Morse
+Moss
+Moyer
+Mueller
+Mull
+Mullet
+Mullins
+Munn
+Murdock
+Murphey
+Murphy
+Murray
+Murry
+Mutchler
+Myers
+Myrick
+Nassar
+Nathan
+Nazzal
+Neal
+Nederveld
+Nelson
+Nguyen
+Nichols
+Nielsen
+Nockton
+Nolan
+Noonan
+Norbury
+Nordlander
+Norris
+Norvell
+Noyes
+Nugent
+Nunn
+O'Brien
+O'Connell
+O'Neill
+O'Steen
+Ober
+Odegard
+Oliver
+Ollmann
+Olson
+Ongley
+Ordway
+Ortiz
+Ouellette
+Overcash
+Overfelt
+Overley
+Owens
+Page
+Paige
+Pardue
+Parham
+Parker
+Parks
+Patterson
+Patton
+Paul
+Payne
+Peck
+Penisson
+Percer
+Perez
+Perlioni
+Perrino
+Peterman
+Peters
+Pfeiffer
+Phelps
+Philip
+Philippe
+Phillips
+Pickett
+Pippenger
+Pistole
+Platzek
+Player
+Poddar
+Poirier
+Poklepovic
+Polk
+Polking
+Pond
+Popish
+Porter
+Pound
+Pounds
+Powell
+Powers
+Prado
+Preston
+Price
+Prichep
+Priour
+Prischmann
+Pryor
+Puckett
+Raglin
+Ralston
+Rampersad
+Ratner
+Rawles
+Ray
+Read
+Reddy
+Reed
+Reese
+Reeves
+Reichenbach
+Reifel
+Rein
+Reiten
+Reiter
+Reitmeier
+Reynolds
+Richardson
+Rider
+Rhinehart
+Ritchie
+Rittenbach
+Roberts
+Robinson
+Rodriguez
+Rogers
+Roper
+Rosemblun
+Rosen
+Rosenberg
+Rosenblatt
+Ross
+Roth
+Rowatt
+Roy
+Royston
+Rozendal
+Rubble
+Ruhlin
+Rupert
+Russell
+Ruthruff
+Ryan
+Rye
+Sabry
+Sachitano
+Sachs
+Sammartino
+Sands
+Saunders
+Savely
+Scales
+Schaefer
+Schafer
+Scheer
+Schild
+Schlitt
+Schmitz
+Schneider
+Schoenberger
+Schoppe
+Scott
+Seay
+Segura
+Selesnick
+Self
+Seligmann
+Sewall
+Shami
+Shampine
+Sharp
+Shaw
+Shefelbine
+Sheldon
+Sherrill
+Shidle
+Shifley
+Shillingsburg
+Shisler
+Shopbell
+Shupack
+Sievert
+Simpson
+Sims
+Sissman
+Smayling
+Smith
+Snyder
+Solomon
+Solon
+Soltero
+Sommers
+Sonneborn
+Sorensen
+Southworth
+Spear
+Speight
+Spencer
+Spruell
+Spudich
+Stacy
+Staebel
+Steele
+Steinhour
+Steinke
+Stepp
+Stevens
+Stewart
+Stickel
+Stine
+Stivers
+Stobb
+Stone
+Stratmann
+Stubbers
+Stuckey
+Stugart
+Sullivan
+Sultan
+Sumrall
+Sunley
+Sunshine
+Sutton
+Swaim
+Swales
+Sweed
+Swick
+Swift
+Swindell
+Swint
+Symonds
+Syzdek
+Szafranski
+Takimoto
+Talbott
+Talwar
+Tanner
+Taslimi
+Tate
+Tatum
+Taylor
+Tchainikov
+Terk
+Thacker
+Thomas
+Thompson
+Thomson
+Thornton
+Thurman
+Thurow
+Tilley
+Tolle
+Towns
+Trafton
+Tran
+Trevas
+Trevino
+Triggs
+Truchard
+Tunison
+Turner
+Twedell
+Tyler
+Tyree
+Unger
+Van
+Vanderzanden
+Vanlandingham
+Varanasi
+Varela
+Varman
+Venier
+Verspoor
+Vick
+Visinsky
+Voltz
+Wagner
+Wake
+Walcott
+Waldron
+Walker
+Wallace
+Walters
+Walton
+Ward
+Wardle
+Warnes
+Warren
+Washington
+Watson
+Watters
+Webber
+Weidenfeller
+Weien
+Weimer
+Weiner
+Weinger
+Weinheimer
+Weirich
+Welch
+Wells
+Wendt
+West
+Westmoreland
+Wex
+Whitaker
+White
+Whitley
+Wiediger
+Wilburn
+Williams
+Williamson
+Willman
+Wilson
+Winger
+Wise
+Wisur
+Witt
+Wong
+Woodbury
+Wooten
+Workman
+Wright
+Wyatt
+Yates
+Yeamans
+Yen
+York
+Yotov
+Younan
+Young
+Zeldin
+Zettner
+Ziegler
+Zitterkopf
+Zucker
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/helloworld/t1/tutorial1.qml b/examples/declarative/tutorials/helloworld/t1/tutorial1.qml
new file mode 100644
index 0000000..4e53b8e
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/t1/tutorial1.qml
@@ -0,0 +1,14 @@
+Rect {
+ id: Page
+ width: 480
+ height: 200
+ color: "LightGrey"
+ Text {
+ id: HelloText
+ text: "Hello world!"
+ font.size: 24
+ font.bold: true
+ y: 30
+ anchors.horizontalCenter: Page.horizontalCenter
+ }
+}
diff --git a/examples/declarative/tutorials/helloworld/t2/Cell.qml b/examples/declarative/tutorials/helloworld/t2/Cell.qml
new file mode 100644
index 0000000..0109251
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/t2/Cell.qml
@@ -0,0 +1,16 @@
+Item {
+ property var color
+
+ id: CellContainer
+ width: 40
+ height: 25
+
+ Rect {
+ anchors.fill: parent
+ color: CellContainer.color
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { HelloText.color = CellContainer.color }
+ }
+}
diff --git a/examples/declarative/tutorials/helloworld/t2/tutorial2.qml b/examples/declarative/tutorials/helloworld/t2/tutorial2.qml
new file mode 100644
index 0000000..6c7e68e
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/t2/tutorial2.qml
@@ -0,0 +1,27 @@
+Rect {
+ id: Page
+ width: 480
+ height: 200
+ color: "LightGrey"
+ 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
+ rows: 2; columns: 3
+ Cell { color: "#ff0000" }
+ Cell { color: "#00ff00" }
+ Cell { color: "#0000ff" }
+ Cell { color: "#ffff00" }
+ Cell { color: "#00ffff" }
+ Cell { color: "#ff00ff" }
+ }
+}
diff --git a/examples/declarative/tutorials/helloworld/t3/Cell.qml b/examples/declarative/tutorials/helloworld/t3/Cell.qml
new file mode 100644
index 0000000..e779406
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/t3/Cell.qml
@@ -0,0 +1,15 @@
+Item {
+ property var color
+
+ id: CellContainer
+ width: 40
+ height: 25
+ Rect {
+ anchors.fill: parent
+ color: CellContainer.color
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { HelloText.color = CellContainer.color }
+ }
+}
diff --git a/examples/declarative/tutorials/helloworld/t3/tutorial3.qml b/examples/declarative/tutorials/helloworld/t3/tutorial3.qml
new file mode 100644
index 0000000..bd89ecf
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/t3/tutorial3.qml
@@ -0,0 +1,59 @@
+Rect {
+ id: Page
+ width: 480
+ height: 200
+ color: "LightGrey"
+ 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"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "down"
+ reversible: true
+ ParallelAnimation {
+ NumericAnimation {
+ properties: "y"
+ duration: 500
+ easing: "easeOutBounce"
+ }
+ ColorAnimation { duration: 500 }
+ }
+ }
+ ]
+ }
+ MouseRegion { id: MouseRegion; anchors.fill: HelloText }
+ GridLayout {
+ id: ColorPicker
+ x: 0
+ anchors.bottom: Page.bottom
+ width: 120; height: 50
+ rows: 2; columns: 3
+ Cell { color: "#ff0000" }
+ Cell { color: "#00ff00" }
+ Cell { color: "#0000ff" }
+ Cell { color: "#ffff00" }
+ Cell { color: "#00ffff" }
+ Cell { color: "#ff00ff" }
+ }
+}
diff --git a/examples/declarative/velocity/Day.qml b/examples/declarative/velocity/Day.qml
new file mode 100644
index 0000000..c70a211
--- /dev/null
+++ b/examples/declarative/velocity/Day.qml
@@ -0,0 +1,111 @@
+Rect {
+ property string day
+ property var stickies
+
+ width: 400
+ height: 500
+ radius: 7
+ pen.color: "black"
+ id: Page
+ Image {
+ x: 10
+ y: 10
+ source: "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
+ }
+ Item {
+ id: Sticky
+ scale: 0.5
+ Image {
+ id: StickyImage
+ source: "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
+ }
+ }
+ }
+ Image {
+ source: "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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "rotation,scale"
+ duration: 200
+ }
+ }
+ ]
+ }
+ }
+}
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..786f364
--- /dev/null
+++ b/examples/declarative/velocity/velocity.qml
@@ -0,0 +1,113 @@
+Rect {
+ color: "lightSteelBlue"
+ width: 800
+ height: 600
+ ListModel {
+ id: List
+ ListElement {
+ name: "Sunday"
+ dayColor: "#808080"
+ notes: [
+ ListElement {
+ noteText: "Lunch"
+ },
+ ListElement {
+ noteText: "Party"
+ }
+ ]
+ }
+ ListElement {
+ name: "Monday"
+ dayColor: "blue"
+ notes: [
+ ListElement {
+ noteText: "Pickup kids"
+ },
+ ListElement {
+ noteText: "Checkout kinetic"
+ },
+ ListElement {
+ noteText: "Read email"
+ }
+ ]
+ }
+ ListElement {
+ name: "Tuesday"
+ dayColor: "yellow"
+ notes: [
+ ListElement {
+ noteText: "Walk dog"
+ },
+ ListElement {
+ noteText: "Buy newspaper"
+ }
+ ]
+ }
+ ListElement {
+ name: "Wednesday"
+ dayColor: "purple"
+ notes: [
+ ListElement {
+ noteText: "Cook dinner"
+ },
+ ListElement {
+ noteText: "Eat dinner"
+ }
+ ]
+ }
+ ListElement {
+ name: "Thursday"
+ dayColor: "blue"
+ notes: [
+ ListElement {
+ noteText: "5:30pm Meeting"
+ },
+ ListElement {
+ noteText: "Weed garden"
+ }
+ ]
+ }
+ ListElement {
+ name: "Friday"
+ dayColor: "green"
+ notes: [
+ ListElement {
+ noteText: "Still work"
+ },
+ ListElement {
+ noteText: "Drink"
+ }
+ ]
+ }
+ ListElement {
+ name: "Saturday"
+ dayColor: "orange"
+ notes: [
+ ListElement {
+ noteText: "Drink"
+ },
+ ListElement {
+ noteText: "Drink"
+ }
+ ]
+ }
+ }
+ Flickable {
+ id: Flick
+ anchors.fill: parent
+ viewportWidth: Lay.width
+ HorizontalLayout {
+ id: Lay
+ Repeater {
+ dataSource: List
+ Component {
+ Day {
+ day: name
+ color: dayColor
+ stickies: notes
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/webview/autosize.qml b/examples/declarative/webview/autosize.qml
new file mode 100644
index 0000000..c32b752
--- /dev/null
+++ b/examples/declarative/webview/autosize.qml
@@ -0,0 +1,59 @@
+// 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: "No width defined."
+ Rect {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ width: Rect.width
+ html: "The width is full."
+ Rect {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ width: Rect.width/2
+ html: "The width is half."
+ Rect {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ idealWidth: Rect.width/2
+ html: "The idealWidth is half."
+ Rect {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ idealWidth: Rect.width/2
+ html: "The_idealWidth_is_half."
+ Rect {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ width: Rect.width/2
+ html: "The_width_is_half."
+ Rect {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ }
+}
diff --git a/examples/declarative/webview/content/SpinSquare.qml b/examples/declarative/webview/content/SpinSquare.qml
new file mode 100644
index 0000000..5e4735e
--- /dev/null
+++ b/examples/declarative/webview/content/SpinSquare.qml
@@ -0,0 +1,24 @@
+Item {
+ properties var period : 250
+ properties var color : "black"
+ id: Root
+
+ Item {
+ x: Root.width/2
+ y: Root.height/2
+ Rect {
+ color: Root.color
+ x: -width/2
+ y: -height/2
+ width: Root.width
+ height: width
+ }
+ rotation: NumericAnimation {
+ from: 0
+ to: 360
+ repeat: true
+ running: true
+ duration: Root.period
+ }
+ }
+}
diff --git a/examples/declarative/webview/inline-html.qml b/examples/declarative/webview/inline-html.qml
new file mode 100644
index 0000000..5f6d410
--- /dev/null
+++ b/examples/declarative/webview/inline-html.qml
@@ -0,0 +1,12 @@
+// Inline HTML with loose formatting can be
+// set on the html property.
+WebView {
+ html:"\
+ <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>"
+}
diff --git a/examples/declarative/webview/qml-in-html.qml b/examples/declarative/webview/qml-in-html.qml
new file mode 100644
index 0000000..29dded5
--- /dev/null
+++ b/examples/declarative/webview/qml-in-html.qml
@@ -0,0 +1,30 @@
+// The WebView supports QML data through the HTML OBJECT tag
+Rect {
+ color:"blue"
+ Flickable {
+ width: parent.width
+ height: parent.height/2
+ viewportWidth: Web.width*Web.scale
+ viewportHeight: Web.height*Web.scale
+ WebView {
+ id: Web
+ width: 250
+ height: 420
+ scale: 0.75
+ smooth: true
+ settings.pluginsEnabled: true
+ html: "<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>"
+ }
+ }
+}
diff --git a/examples/declarative/webview/transparent.qml b/examples/declarative/webview/transparent.qml
new file mode 100644
index 0000000..8614822
--- /dev/null
+++ b/examples/declarative/webview/transparent.qml
@@ -0,0 +1,11 @@
+// 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 <b>World!</b>"
+ }
+}
diff --git a/examples/declarative/xmldata/daringfireball.qml b/examples/declarative/xmldata/daringfireball.qml
new file mode 100644
index 0000000..3877adf
--- /dev/null
+++ b/examples/declarative/xmldata/daringfireball.qml
@@ -0,0 +1,59 @@
+Rect {
+ color: "white"
+ width: 600
+ height: 600
+ resources: [
+ XmlListModel {
+ id: feedModel
+ source: "http://daringfireball.net/index.xml"
+ query: "doc($src)/feed/entry"
+ namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';"
+ Role {
+ name: "title"
+ query: "title/string()"
+ }
+ Role {
+ name: "tagline"
+ query: "author/name/string()"
+ }
+ Role {
+ name: "content"
+ query: "content/string()"
+ isCData: true
+ }
+ },
+ 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) }
+ }
+ }
+ }
+ ]
+ ListView {
+ id: list
+ anchors.fill: parent
+ clip: true
+ model: feedModel
+ delegate: feedDelegate
+ }
+}
diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml
new file mode 100644
index 0000000..206c85f
--- /dev/null
+++ b/examples/declarative/xmldata/yahoonews.qml
@@ -0,0 +1,113 @@
+Rect {
+ gradient: Gradient {
+ GradientStop { position: 0; color: "black" }
+ GradientStop { position: 1.0; color: "#AAAAAA" }
+ }
+ width: 600
+ height: 600
+ resources: [
+ XmlListModel {
+ id: feedModel
+ source: "http://rss.news.yahoo.com/rss/oceania"
+ query: "doc($src)/rss/channel/item"
+ Role {
+ name: "title"
+ query: "title/string()"
+ }
+ Role {
+ name: "link"
+ query: "link/string()"
+ }
+ Role {
+ name: "description"
+ query: "description/string()"
+ isCData: true
+ }
+ },
+ 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: '<a href=\'' + link + '\'>' + title + '</a>'
+ 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
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "Details"
+ reversible: true
+ SequentialAnimation {
+ NumericAnimation {
+ duration: 200
+ properties: "height"
+ easing: "easeOutQuad"
+ }
+ NumericAnimation {
+ duration: 200
+ properties: "opacity"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ ListView {
+ id: list
+ x: 10
+ y: 10
+ width: parent.width - 20
+ height: parent.height - 20
+ clip: true
+ model: feedModel
+ delegate: feedDelegate
+ currentItemPositioning: "Snap"
+ }
+}
diff --git a/examples/examples.pro b/examples/examples.pro
index bfcf9b4..8a20845 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -21,6 +21,7 @@ SUBDIRS = \
tutorials \
widgets \
uitools \
+ declarative \
xml \
script
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 0c6e09a..02336af 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -36,7 +36,7 @@ INCLUDEPATH = $$QMAKE_INCDIR_QT $$INCLUDEPATH #prepending prevents us from picki
win32:INCLUDEPATH += $$QMAKE_INCDIR_QT/ActiveQt
# As order does matter for static libs, we reorder the QT variable here
-TMPLIBS = webkit phonon dbus testlib script scripttools svg qt3support sql xmlpatterns xml opengl gui network core
+TMPLIBS = declarative webkit phonon dbus testlib script scripttools svg qt3support sql xmlpatterns xml opengl gui network core
for(QTLIB, $$list($$TMPLIBS)) {
contains(QT, $$QTLIB): QT_ORDERED += $$QTLIB
}
@@ -151,6 +151,7 @@ for(QTLIB, $$list($$lower($$unique(QT)))) {
else:isEqual(QTLIB, dbus):qlib = QtDBus
else:isEqual(QTLIB, phonon):qlib = phonon
else:isEqual(QTLIB, webkit):qlib = QtWebKit
+ else:isEqual(QTLIB, declarative):qlib = QtDeclarative
else:message("Unknown QT: $$QTLIB"):qlib =
!isEmpty(qlib) {
target_qt:isEqual(TARGET, qlib) {
diff --git a/mkspecs/linux-g++-x11egl/qmake.conf b/mkspecs/linux-g++-x11egl/qmake.conf
new file mode 100644
index 0000000..e9e5abc
--- /dev/null
+++ b/mkspecs/linux-g++-x11egl/qmake.conf
@@ -0,0 +1,26 @@
+#
+# qmake configuration for linux-g++
+#
+
+MAKEFILE_GENERATOR = UNIX
+TEMPLATE = app
+CONFIG += qt warn_on release incremental link_prl
+QT += core gui
+QMAKE_INCREMENTAL_STYLE = sublib
+
+include(../common/g++.conf)
+include(../common/linux.conf)
+load(qt_config)
+
+QMAKE_INCDIR_OPENGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
+QMAKE_INCDIR_OPENGL_QT = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
+
+QMAKE_LIBDIR_OPENGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+QMAKE_LIBDIR_OPENGL_QT = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+
+QMAKE_LIBS_OPENGL = -lGLESv2 -lEGL
+QMAKE_LIBS += -Wl,-rpath=$(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+
+QMAKE_LIBS_OPENGL_QT = -lGLESv2 -lEGL
+
+QMAKE_RPATH = -Wl,-rpath,
diff --git a/mkspecs/linux-g++-x11egl/qplatformdefs.h b/mkspecs/linux-g++-x11egl/qplatformdefs.h
new file mode 100644
index 0000000..e52b07a
--- /dev/null
+++ b/mkspecs/linux-g++-x11egl/qplatformdefs.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMDEFS_H
+#define QPLATFORMDEFS_H
+
+// Get Qt defines/settings
+
+#include "qglobal.h"
+
+// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs
+
+// 1) need to reset default environment if _BSD_SOURCE is defined
+// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0
+// 3) it seems older glibc need this to include the X/Open stuff
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <unistd.h>
+
+
+// We are hot - unistd.h should have turned on the specific APIs we requested
+
+#include <features.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <dlfcn.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/ipc.h>
+#include <sys/time.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#ifndef QT_NO_IPV6IFNAME
+#include <net/if.h>
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_STATBUF struct stat64
+#define QT_STATBUF4TSTAT struct stat64
+#define QT_STAT ::stat64
+#define QT_FSTAT ::fstat64
+#define QT_LSTAT ::lstat64
+#define QT_OPEN ::open64
+#define QT_TRUNCATE ::truncate64
+#define QT_FTRUNCATE ::ftruncate64
+#define QT_LSEEK ::lseek64
+#else
+#define QT_STATBUF struct stat
+#define QT_STATBUF4TSTAT struct stat
+#define QT_STAT ::stat
+#define QT_FSTAT ::fstat
+#define QT_LSTAT ::lstat
+#define QT_OPEN ::open
+#define QT_TRUNCATE ::truncate
+#define QT_FTRUNCATE ::ftruncate
+#define QT_LSEEK ::lseek
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_FOPEN ::fopen64
+#define QT_FSEEK ::fseeko64
+#define QT_FTELL ::ftello64
+#define QT_FGETPOS ::fgetpos64
+#define QT_FSETPOS ::fsetpos64
+#define QT_FPOS_T fpos64_t
+#define QT_OFF_T off64_t
+#else
+#define QT_FOPEN ::fopen
+#define QT_FSEEK ::fseek
+#define QT_FTELL ::ftell
+#define QT_FGETPOS ::fgetpos
+#define QT_FSETPOS ::fsetpos
+#define QT_FPOS_T fpos_t
+#define QT_OFF_T long
+#endif
+
+#define QT_STAT_REG S_IFREG
+#define QT_STAT_DIR S_IFDIR
+#define QT_STAT_MASK S_IFMT
+#define QT_STAT_LNK S_IFLNK
+#define QT_SOCKET_CONNECT ::connect
+#define QT_SOCKET_BIND ::bind
+#define QT_FILENO fileno
+#define QT_CLOSE ::close
+#define QT_READ ::read
+#define QT_WRITE ::write
+#define QT_ACCESS ::access
+#define QT_GETCWD ::getcwd
+#define QT_CHDIR ::chdir
+#define QT_MKDIR ::mkdir
+#define QT_RMDIR ::rmdir
+#define QT_OPEN_LARGEFILE O_LARGEFILE
+#define QT_OPEN_RDONLY O_RDONLY
+#define QT_OPEN_WRONLY O_WRONLY
+#define QT_OPEN_RDWR O_RDWR
+#define QT_OPEN_CREAT O_CREAT
+#define QT_OPEN_TRUNC O_TRUNC
+#define QT_OPEN_APPEND O_APPEND
+
+#define QT_SIGNAL_RETTYPE void
+#define QT_SIGNAL_ARGS int
+#define QT_SIGNAL_IGNORE SIG_IGN
+
+#if defined(__GLIBC__) && (__GLIBC__ >= 2)
+#define QT_SOCKLEN_T socklen_t
+#else
+#define QT_SOCKLEN_T int
+#endif
+
+#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
+#define QT_SNPRINTF ::snprintf
+#define QT_VSNPRINTF ::vsnprintf
+#endif
+
+
+#endif // QPLATFORMDEFS_H
diff --git a/mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf b/mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf
new file mode 100644
index 0000000..3611421
--- /dev/null
+++ b/mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf
@@ -0,0 +1,20 @@
+#
+# qmake configuration for building with arm-none-linux-gnueabi-g++
+#
+
+include(../../common/g++.conf)
+include(../../common/linux.conf)
+include(../../common/qws.conf)
+
+# modifications to g++.conf
+QMAKE_CC = arm-none-linux-gnueabi-gcc
+QMAKE_CXX = arm-none-linux-gnueabi-g++
+QMAKE_LINK = arm-none-linux-gnueabi-g++
+QMAKE_LINK_SHLIB = arm-none-linux-gnueabi-g++
+
+# modifications to linux.conf
+QMAKE_AR = arm-none-linux-gnueabi-ar cqs
+QMAKE_OBJCOPY = arm-none-linux-gnueabi-objcopy
+QMAKE_STRIP = arm-none-linux-gnueabi-strip
+
+load(qt_config)
diff --git a/mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h b/mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h
new file mode 100644
index 0000000..919ac0f
--- /dev/null
+++ b/mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** 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 "../../linux-g++/qplatformdefs.h"
diff --git a/src/3rdparty/easing/legal.qdoc b/src/3rdparty/easing/legal.qdoc
index 25f67e1..1be5f66 100644
--- a/src/3rdparty/easing/legal.qdoc
+++ b/src/3rdparty/easing/legal.qdoc
@@ -1,7 +1,7 @@
/*!
\page legal-easing.html
\title Easing Equations by Robert Penner
-\ingroup animation
+\ingroup group_animation
\legalese
\code
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 61d61df..962e2fb 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -41,7 +41,7 @@
/*!
\class QAbstractAnimation
- \ingroup animation
+ \ingroup group_animation
\brief The QAbstractAnimation class is the base of all animations.
\since 4.6
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index a3fa93a..9303034 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QVariantAnimation
- \ingroup animation
+ \ingroup group_animation
\brief The QVariantAnimation class provides an abstract base class for animations.
\since 4.6
@@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE
setStartValue() and setEndValue(), and finally call start() to
start the animation. QVariantAnimation will interpolate the
property of the target object and emit valueChanged(). To react to
- a change in the current value you have to reimplement the
+ a change in the current value you have to implement the
updateCurrentValue() virtual function.
It is also possible to set values at specified steps situated
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 51ca43e..e6fdc08 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -1515,7 +1515,7 @@ QString QTextDecoder::toUnicode(const QByteArray &ba)
cannot be detected from the content provided, \a defaultCodec is
returned.
- \sa codecForUtfText
+ \sa codecForUtfText()
*/
QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
{
@@ -1561,7 +1561,7 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba)
cannot be detected from the content provided, \a defaultCodec is
returned.
- \sa codecForHtml
+ \sa codecForHtml()
*/
QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec)
{
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 3990c7d..f6c90f7 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1137,6 +1137,11 @@ class QDataStream;
# else
# define Q_SVG_EXPORT Q_DECL_IMPORT
# endif
+# if defined(QT_BUILD_DECLARATIVE_LIB)
+# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT
+# else
+# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT
+# endif
# if defined(QT_BUILD_OPENGL_LIB)
# define Q_OPENGL_EXPORT Q_DECL_EXPORT
# else
@@ -1179,6 +1184,7 @@ class QDataStream;
# define Q_SQL_EXPORT Q_DECL_IMPORT
# define Q_NETWORK_EXPORT Q_DECL_IMPORT
# define Q_SVG_EXPORT Q_DECL_IMPORT
+# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT
# define Q_CANVAS_EXPORT Q_DECL_IMPORT
# define Q_OPENGL_EXPORT Q_DECL_IMPORT
# define Q_XML_EXPORT Q_DECL_IMPORT
@@ -1205,6 +1211,7 @@ class QDataStream;
# define Q_SQL_EXPORT Q_DECL_EXPORT
# define Q_NETWORK_EXPORT Q_DECL_EXPORT
# define Q_SVG_EXPORT Q_DECL_EXPORT
+# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT
# define Q_OPENGL_EXPORT Q_DECL_EXPORT
# define Q_XML_EXPORT Q_DECL_EXPORT
# define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT
@@ -1217,6 +1224,7 @@ class QDataStream;
# define Q_SQL_EXPORT
# define Q_NETWORK_EXPORT
# define Q_SVG_EXPORT
+# define Q_DECLARATIVE_EXPORT
# define Q_OPENGL_EXPORT
# define Q_XML_EXPORT
# define Q_XMLPATTERNS_EXPORT
@@ -2251,6 +2259,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
#define QT_MODULE_TEST 0x04000
#define QT_MODULE_DBUS 0x08000
#define QT_MODULE_SCRIPTTOOLS 0x10000
+#define QT_MODULE_DECLARATIVE 0x20000
/* Qt editions */
#define QT_EDITION_CONSOLE (QT_MODULE_CORE \
@@ -2278,6 +2287,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
| QT_MODULE_QT3SUPPORTLIGHT \
| QT_MODULE_QT3SUPPORT \
| QT_MODULE_SVG \
+ | QT_MODULE_DECLARATIVE \
| QT_MODULE_GRAPHICSVIEW \
| QT_MODULE_HELP \
| QT_MODULE_TEST \
@@ -2340,6 +2350,9 @@ QT_LICENSED_MODULE(Qt3Support)
#if (QT_EDITION & QT_MODULE_SVG)
QT_LICENSED_MODULE(Svg)
#endif
+#if (QT_EDITION & QT_MODULE_DECLARATIVE)
+QT_LICENSED_MODULE(Declarative)
+#endif
#if (QT_EDITION & QT_MODULE_ACTIVEQT)
QT_LICENSED_MODULE(ActiveQt)
#endif
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index ecef555..4d7d8b7 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -32,7 +32,8 @@ HEADERS += \
kernel/qsharedmemory_p.h \
kernel/qsystemsemaphore.h \
kernel/qsystemsemaphore_p.h \
- kernel/qfunctions_p.h
+ kernel/qfunctions_p.h \
+ kernel/qmetaobjectbuilder_p.h
SOURCES += \
kernel/qabstracteventdispatcher.cpp \
@@ -54,6 +55,7 @@ SOURCES += \
kernel/qcoreglobaldata.cpp \
kernel/qsharedmemory.cpp \
kernel/qsystemsemaphore.cpp \
+ kernel/qmetaobjectbuilder.cpp \
kernel/qpointer.cpp
win32 {
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index 935c0aa..dd4f3f3 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -467,6 +467,21 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
return qEmptyModel();
}
+const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames()
+{
+ static QHash<int,QByteArray> roleNames;
+ if (roleNames.isEmpty()) {
+ roleNames[Qt::DisplayRole] = "display";
+ roleNames[Qt::DecorationRole] = "decoration";
+ roleNames[Qt::EditRole] = "edit";
+ roleNames[Qt::ToolTipRole] = "toolTip";
+ roleNames[Qt::StatusTipRole] = "statusTip";
+ roleNames[Qt::WhatsThisRole] = "whatsThis";
+ }
+
+ return roleNames;
+}
+
void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
{
if (data->index.isValid()) {
@@ -1832,6 +1847,25 @@ QSize QAbstractItemModel::span(const QModelIndex &) const
}
/*!
+ Sets the model's role names to \a roleNames.
+*/
+void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames)
+{
+ Q_D(QAbstractItemModel);
+ d->roleNames = roleNames;
+}
+
+/*!
+ Returns the model's role names.
+*/
+const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const
+{
+ Q_D(const QAbstractItemModel);
+ qDebug() << "roles" << d->roleNames;
+ return d->roleNames;
+}
+
+/*!
Called to let the model know that it should submit whatever it has cached
to the permanent storage. Typically used for row editing.
diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h
index b062768..00cd817 100644
--- a/src/corelib/kernel/qabstractitemmodel.h
+++ b/src/corelib/kernel/qabstractitemmodel.h
@@ -220,6 +220,9 @@ public:
Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const;
virtual QSize span(const QModelIndex &index) const;
+ void setRoleNames(const QHash<int,QByteArray> &roleNames);
+ const QHash<int,QByteArray> &roleNames() const;
+
#ifdef Q_NO_USING_KEYWORD
inline QObject *parent() const { return QObject::parent(); }
#else
diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h
index 27f1b28..fb42e77 100644
--- a/src/corelib/kernel/qabstractitemmodel_p.h
+++ b/src/corelib/kernel/qabstractitemmodel_p.h
@@ -78,7 +78,7 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QAbstractItemModel)
public:
- QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1) {}
+ QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {}
void removePersistentIndexData(QPersistentModelIndexData *data);
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
void rowsInserted(const QModelIndex &parent, int first, int last);
@@ -143,6 +143,9 @@ public:
} persistent;
Qt::DropActions supportedDragActions;
+
+ QHash<int,QByteArray> roleNames;
+ static const QHash<int,QByteArray> &defaultRoleNames();
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index d6b0174..bbd0695 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -290,7 +290,7 @@ QEvent::~QEvent()
/*!
\property QEvent::accepted
- the accept flag of the event object
+ \brief The accept flag of the event object
Setting the accept parameter indicates that the event receiver
wants the event. Unwanted events might be propagated to the parent
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 18188a8..5c96f71 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -58,6 +58,7 @@ class Q_CORE_EXPORT QEvent // event base class
Q_GADGET
QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
Q_ENUMS(Type)
+
public:
enum Type {
/*
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index b65f956..7502842 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -159,7 +159,8 @@ enum PropertyFlags {
ResolveEditable = 0x00080000,
User = 0x00100000,
ResolveUser = 0x00200000,
- Notify = 0x00400000
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
};
enum MethodFlags {
@@ -179,6 +180,10 @@ enum MethodFlags {
MethodScriptable = 0x40
};
+enum MetaObjectFlags {
+ DynamicMetaObject = 0x01
+};
+
struct QMetaObjectPrivate
{
int revision;
@@ -188,6 +193,7 @@ struct QMetaObjectPrivate
int propertyCount, propertyData;
int enumeratorCount, enumeratorData;
int constructorCount, constructorData;
+ int flags;
};
static inline const QMetaObjectPrivate *priv(const uint* data)
@@ -271,6 +277,17 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
}
/*!
+ \internal
+*/
+int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
+{
+ if (QMetaObject *mo = object->d_ptr->metaObject)
+ return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv);
+ else
+ return object->qt_metacall(cl, idx, argv);
+}
+
+/*!
\fn const char *QMetaObject::className() const
Returns the class name.
@@ -690,6 +707,14 @@ int QMetaObject::indexOfProperty(const char *name) const
}
m = m->d.superdata;
}
+
+ if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){
+ QAbstractDynamicMetaObject *me =
+ const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
+
+ i = me->createProperty(name, 0);
+ }
+
return i;
}
@@ -1320,6 +1345,16 @@ int QMetaMethod::attributes() const
}
/*!
+ Returns this method's index.
+*/
+int QMetaMethod::methodIndex() const
+{
+ if (!mobj)
+ return -1;
+ return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
+}
+
+/*!
Returns the access specification of this method (private,
protected, or public).
@@ -1519,7 +1554,7 @@ bool QMetaMethod::invoke(QObject *object,
// recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
if (connectionType == Qt::DirectConnection) {
- return object->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
+ return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
} else {
if (returnValue.data()) {
qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
@@ -2029,6 +2064,16 @@ int QMetaProperty::userType() const
}
/*!
+ Returns this property's index.
+*/
+int QMetaProperty::propertyIndex() const
+{
+ if (!mobj)
+ return -1;
+ return idx + mobj->propertyOffset();
+}
+
+/*!
Returns true if the property's type is an enumeration value that
is used as a flag; otherwise returns false.
@@ -2133,9 +2178,8 @@ QVariant QMetaProperty::read(const QObject *object) const
value = QVariant(t, (void*)0);
argv[0] = value.data();
}
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::ReadProperty,
- idx + mobj->propertyOffset(),
- argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
+ idx + mobj->propertyOffset(), argv);
if (argv[1] == 0)
// "value" was changed
return value;
@@ -2200,7 +2244,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
argv[0] = &v;
else
argv[0] = v.data();
- object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
return true;
}
@@ -2217,7 +2261,7 @@ bool QMetaProperty::reset(QObject *object) const
if (!object || !mobj || !isResettable())
return false;
void *argv[] = { 0 };
- object->qt_metacall(QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
return true;
}
@@ -2329,8 +2373,8 @@ bool QMetaProperty::isDesignable(const QObject *object) const
bool b = flags & Designable;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyDesignable,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable,
+ idx + mobj->propertyOffset(), argv);
}
return b;
@@ -2355,8 +2399,8 @@ bool QMetaProperty::isScriptable(const QObject *object) const
bool b = flags & Scriptable;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyScriptable,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
@@ -2379,8 +2423,8 @@ bool QMetaProperty::isStored(const QObject *object) const
bool b = flags & Stored;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyStored,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
@@ -2406,13 +2450,24 @@ bool QMetaProperty::isUser(const QObject *object) const
bool b = flags & User;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyUser,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
/*!
+ \internal
+*/
+bool QMetaProperty::isDynamic() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Dynamic;
+}
+
+/*!
\obsolete
Returns true if the property is editable for the given \a object;
@@ -2432,8 +2487,8 @@ bool QMetaProperty::isEditable(const QObject *object) const
bool b = flags & Editable;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyEditable,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 18c488a..26e8b53 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -69,6 +69,7 @@ public:
MethodType methodType() const;
enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 };
int attributes() const;
+ int methodIndex() const;
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
@@ -178,6 +179,7 @@ public:
const char *typeName() const;
QVariant::Type type() const;
int userType() const;
+ int propertyIndex() const;
bool isReadable() const;
bool isWritable() const;
@@ -187,6 +189,7 @@ public:
bool isStored(const QObject *obj = 0) const;
bool isEditable(const QObject *obj = 0) const;
bool isUser(const QObject *obj = 0) const;
+ bool isDynamic() const;
bool isFlagType() const;
bool isEnumType() const;
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..de75bde
--- /dev/null
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -0,0 +1,2446 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetaobjectbuilder_p.h"
+#include <QDebug>
+
+/*!
+ \class QMetaObjectBuilder
+ \brief The QMetaObjectBuilder class supports building QMetaObject objects at runtime.
+
+*/
+
+/*!
+ \enum QMetaObjectBuilder::AddMember
+ This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
+
+ \value ClassName Add the class name.
+ \value SuperClass Add the super class.
+ \value Methods Add methods that aren't signals or slots.
+ \value Signals Add signals.
+ \value Slots Add slots.
+ \value Constructors Add constructors.
+ \value Properties Add properties.
+ \value Enumerators Add enumerators.
+ \value ClassInfos Add items of class information.
+ \value RelatedMetaObjects Add related meta objects.
+ \value StaticMetacall Add the static metacall function.
+ \value PublicMethods Add public methods (ignored for signals).
+ \value ProtectedMethods Add protected methods (ignored for signals).
+ \value PrivateMethods All private methods (ignored for signals).
+ \value AllMembers Add all members.
+ \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
+*/
+
+/*!
+ \enum QMetaObjectBuilder::MetaObjectFlag
+ This enum defines flags for the class being constructed.
+
+ \value DynamicMetaObject
+ */
+
+// copied from moc's generator.cpp
+uint qvariant_nameToType(const char* name)
+{
+ if (!name)
+ return 0;
+
+ if (strcmp(name, "QVariant") == 0)
+ return 0xffffffff;
+ if (strcmp(name, "QCString") == 0)
+ return QMetaType::QByteArray;
+ if (strcmp(name, "Q_LLONG") == 0)
+ return QMetaType::LongLong;
+ if (strcmp(name, "Q_ULLONG") == 0)
+ return QMetaType::ULongLong;
+ if (strcmp(name, "QIconSet") == 0)
+ return QMetaType::QIcon;
+
+ uint tp = QMetaType::type(name);
+ return tp < QMetaType::User ? tp : 0;
+}
+
+/*
+ Returns true if the type is a QVariant types.
+*/
+bool isVariantType(const char* type)
+{
+ return qvariant_nameToType(type) != 0;
+}
+
+// copied from qmetaobject.cpp
+// do not touch without touching the moc as well
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+};
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData;
+ int flags;
+};
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+// end of copied lines from qmetaobject.cpp
+
+class QMetaMethodBuilderPrivate
+{
+public:
+ QMetaMethodBuilderPrivate
+ (QMetaMethod::MethodType _methodType,
+ const QByteArray& _signature,
+ const QByteArray& _returnType = QByteArray(),
+ QMetaMethod::Access _access = QMetaMethod::Public)
+ : signature(QMetaObject::normalizedSignature(_signature.constData())),
+ returnType(QMetaObject::normalizedType(_returnType)),
+ attributes(((int)_access) | (((int)_methodType) << 2))
+ {
+ }
+
+ QByteArray signature;
+ QByteArray returnType;
+ QList<QByteArray> parameterNames;
+ QByteArray tag;
+ int attributes;
+
+ QMetaMethod::MethodType methodType() const
+ {
+ return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
+ }
+
+ QMetaMethod::Access access() const
+ {
+ return (QMetaMethod::Access)(attributes & AccessMask);
+ }
+
+ void setAccess(QMetaMethod::Access value)
+ {
+ attributes = ((attributes & ~AccessMask) | (int)value);
+ }
+};
+
+class QMetaPropertyBuilderPrivate
+{
+public:
+ QMetaPropertyBuilderPrivate
+ (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1)
+ : name(_name),
+ type(QMetaObject::normalizedType(_type.constData())),
+ flags(Readable | Writable), notifySignal(-1)
+ {
+ if (notifierIdx >= 0) {
+ flags |= Notify;
+ notifySignal = notifierIdx;
+ }
+ }
+
+ QByteArray name;
+ QByteArray type;
+ int flags;
+ int notifySignal;
+
+ bool flag(int f) const
+ {
+ return ((flags & f) != 0);
+ }
+
+ void setFlag(int f, bool value)
+ {
+ if (value)
+ flags |= f;
+ else
+ flags &= ~f;
+ }
+};
+
+class QMetaEnumBuilderPrivate
+{
+public:
+ QMetaEnumBuilderPrivate(const QByteArray& _name)
+ : name(_name), isFlag(false)
+ {
+ }
+
+ QByteArray name;
+ bool isFlag;
+ QList<QByteArray> keys;
+ QList<int> values;
+};
+
+class QMetaObjectBuilderPrivate
+{
+public:
+ QMetaObjectBuilderPrivate()
+ : flags(0)
+ {
+ superClass = &QObject::staticMetaObject;
+ staticMetacallFunction = 0;
+ }
+
+ QByteArray className;
+ const QMetaObject *superClass;
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
+ QList<QMetaMethodBuilderPrivate> methods;
+ QList<QMetaMethodBuilderPrivate> constructors;
+ QList<QMetaPropertyBuilderPrivate> properties;
+ QList<QByteArray> classInfoNames;
+ QList<QByteArray> classInfoValues;
+ QList<QMetaEnumBuilderPrivate> enumerators;
+ QList<const QMetaObject *> relatedMetaObjects;
+ int flags;
+};
+
+/*!
+ Constructs a new QMetaObjectBuilder.
+*/
+QMetaObjectBuilder::QMetaObjectBuilder()
+{
+ d = new QMetaObjectBuilderPrivate();
+}
+
+/*!
+ Constructs a new QMetaObjectBuilder which is a copy of the
+ meta object information in \a prototype. Note: the super class
+ contents for \a prototype are not copied, only the immediate
+ class that is defined by \a prototype.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+
+ \sa addMetaObject()
+*/
+QMetaObjectBuilder::QMetaObjectBuilder
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ d = new QMetaObjectBuilderPrivate();
+ addMetaObject(prototype, members);
+}
+
+/*!
+ Destroys this meta object builder.
+*/
+QMetaObjectBuilder::~QMetaObjectBuilder()
+{
+ delete d;
+}
+
+/*!
+ Returns the name of the class being constructed by this
+ meta object builder. The default value is an empty QByteArray.
+
+ \sa setClassName(), superClass()
+*/
+QByteArray QMetaObjectBuilder::className() const
+{
+ return d->className;
+}
+
+/*!
+ Sets the \a name of the class being constructed by this
+ meta object builder.
+
+ \sa className(), setSuperClass()
+*/
+void QMetaObjectBuilder::setClassName(const QByteArray& name)
+{
+ d->className = name;
+}
+
+/*!
+ Returns the superclass meta object of the class being constructed
+ by this meta object builder. The default value is the meta object
+ for QObject.
+
+ \sa setSuperClass(), className()
+*/
+const QMetaObject *QMetaObjectBuilder::superClass() const
+{
+ return d->superClass;
+}
+
+/*!
+ Sets the superclass meta object of the class being constructed
+ by this meta object builder to \a meta. The \a meta parameter
+ must not be null.
+
+ \sa superClass(), setClassName()
+*/
+void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ d->superClass = meta;
+}
+
+/*!
+ Returns the flags of the class being constructed by this meta object
+ builder.
+
+ \sa setFlags()
+*/
+QMetaObjectBuilder::MetaObjectFlags QMetaObjectBuilder::flags() const
+{
+ return (QMetaObjectBuilder::MetaObjectFlags)d->flags;
+}
+
+/*!
+ Sets the \a flags of the class being constructed by this meta object
+ builder.
+
+ \sa flags()
+*/
+void QMetaObjectBuilder::setFlags(MetaObjectFlags flags)
+{
+ d->flags = flags;
+}
+
+/*!
+ Returns the number of methods in this class, excluding the number
+ of methods in the base class. These include signals and slots
+ as well as normal member functions.
+
+ \sa addMethod(), method(), removeMethod(), indexOfMethod()
+*/
+int QMetaObjectBuilder::methodCount() const
+{
+ return d->methods.size();
+}
+
+/*!
+ Returns the number of constructors in this class.
+
+ \sa addConstructor(), constructor(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+int QMetaObjectBuilder::constructorCount() const
+{
+ return d->constructors.size();
+}
+
+/*!
+ Returns the number of properties in this class, excluding the number
+ of properties in the base class.
+
+ \sa addProperty(), property(), removeProperty(), indexOfProperty()
+*/
+int QMetaObjectBuilder::propertyCount() const
+{
+ return d->properties.size();
+}
+
+/*!
+ Returns the number of enumerators in this class, excluding the
+ number of enumerators in the base class.
+
+ \sa addEnumerator(), enumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+int QMetaObjectBuilder::enumeratorCount() const
+{
+ return d->enumerators.size();
+}
+
+/*!
+ Returns the number of items of class information in this class,
+ exclusing the number of items of class information in the base class.
+
+ \sa addClassInfo(), classInfoName(), classInfoValue()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+int QMetaObjectBuilder::classInfoCount() const
+{
+ return d->classInfoNames.size();
+}
+
+/*!
+ Returns the number of related meta objects that are associated
+ with this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa addRelatedMetaObject(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::relatedMetaObjectCount() const
+{
+ return d->relatedMetaObjects.size();
+}
+
+/*!
+ Adds a new public method to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the method. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class with the specified
+ \a signature and \a returnType. Returns an object that can be
+ used to adjust the other attributes of the method. The \a signature
+ and \a returnType will be normalized before they are added to
+ the class. If \a returnType is empty, then it indicates that
+ the method has \c{void} as its return type.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod
+ (const QByteArray& signature, const QByteArray& returnType)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Method, signature, returnType));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class that has the same information as
+ \a prototype. This is used to clone the methods of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the method.
+
+ This function will detect if \a prototype is an ordinary method,
+ signal, slot, or constructor and act accordingly.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
+{
+ QMetaMethodBuilder method;
+ if (prototype.methodType() == QMetaMethod::Method)
+ method = addMethod(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Signal)
+ method = addSignal(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Slot)
+ method = addSlot(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Constructor)
+ method = addConstructor(prototype.signature());
+ method.setReturnType(prototype.typeName());
+ method.setParameterNames(prototype.parameterNames());
+ method.setTag(prototype.tag());
+ method.setAccess(prototype.access());
+ method.setAttributes(prototype.attributes());
+ return method;
+}
+
+/*!
+ Adds a new public slot to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the slot. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSignal(), indexOfSlot()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new signal to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the signal. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSlot(), indexOfSignal()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Signal, signature, QByteArray(), QMetaMethod::Protected));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new constructor to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the constructor. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
+{
+ int index = d->constructors.size();
+ d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature));
+ return QMetaMethodBuilder(this, -(index + 1));
+}
+
+/*!
+ Adds a new constructor to this class that has the same information as
+ \a prototype. This is used to clone the constructors of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the constructor.
+
+ This function requires that \a prototype be a constructor.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
+{
+ Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
+ QMetaMethodBuilder ctor = addConstructor(prototype.signature());
+ ctor.setReturnType(prototype.typeName());
+ ctor.setParameterNames(prototype.parameterNames());
+ ctor.setTag(prototype.tag());
+ ctor.setAccess(prototype.access());
+ ctor.setAttributes(prototype.attributes());
+ return ctor;
+}
+
+/*!
+ Adds a new readable/writable property to this class with the
+ specified \a name and \a type. Returns an object that can be used
+ to adjust the other attributes of the property. The \a type will
+ be normalized before it is added to the class. \a notifierId will
+ be registered as the property's \e notify signal.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty
+ (const QByteArray& name, const QByteArray& type, int notifierId)
+{
+ int index = d->properties.size();
+ d->properties.append(QMetaPropertyBuilderPrivate(name, type, notifierId));
+ return QMetaPropertyBuilder(this, index);
+}
+
+/*!
+ Adds a new property to this class that has the same information as
+ \a prototype. This is used to clone the properties of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the property.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
+{
+ QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
+ property.setReadable(prototype.isReadable());
+ property.setWritable(prototype.isWritable());
+ property.setResettable(prototype.isResettable());
+ property.setDesignable(prototype.isDesignable());
+ property.setScriptable(prototype.isScriptable());
+ property.setStored(prototype.isStored());
+ property.setEditable(prototype.isEditable());
+ property.setUser(prototype.isUser());
+ property.setStdCppSet(prototype.hasStdCppSet());
+ property.setEnumOrFlag(prototype.isEnumType());
+ if (prototype.hasNotifySignal()) {
+ // Find an existing method for the notify signal, or add a new one.
+ QMetaMethod method = prototype.notifySignal();
+ int index = indexOfMethod(method.signature());
+ if (index == -1)
+ index = addMethod(method).index();
+ d->properties[property._index].notifySignal = index;
+ d->properties[property._index].setFlag(Notify, true);
+ }
+ return property;
+}
+
+/*!
+ Adds a new enumerator to this class with the specified
+ \a name. Returns an object that can be used to adjust
+ the other attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
+{
+ int index = d->enumerators.size();
+ d->enumerators.append(QMetaEnumBuilderPrivate(name));
+ return QMetaEnumBuilder(this, index);
+}
+
+/*!
+ Adds a new enumerator to this class that has the same information as
+ \a prototype. This is used to clone the enumerators of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
+{
+ QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setIsFlag(prototype.isFlag());
+ int count = prototype.keyCount();
+ for (int index = 0; index < count; ++index)
+ en.addKey(prototype.key(index), prototype.value(index));
+ return en;
+}
+
+/*!
+ Adds \a name and \a value as an item of class information to this class.
+ Returns the index of the new item of class information.
+
+ \sa classInfoCount(), classInfoName(), classInfoValue()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
+{
+ int index = d->classInfoNames.size();
+ d->classInfoNames += name;
+ d->classInfoValues += value;
+ return index;
+}
+
+/*!
+ Adds \a meta to this class as a related meta object. Returns
+ the index of the new related meta object entry.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ int index = d->relatedMetaObjects.size();
+ d->relatedMetaObjects.append(meta);
+ return index;
+}
+
+/*!
+ Adds the contents of \a prototype to this meta object builder.
+ This function is useful for cloning the contents of an existing QMetaObject.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+*/
+void QMetaObjectBuilder::addMetaObject
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ Q_ASSERT(prototype);
+ int index;
+
+ if ((members & ClassName) != 0)
+ d->className = prototype->className();
+
+ if ((members & SuperClass) != 0)
+ d->superClass = prototype->superClass();
+
+ if ((members & (Methods | Signals | Slots)) != 0) {
+ for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
+ QMetaMethod method = prototype->method(index);
+ if (method.methodType() != QMetaMethod::Signal) {
+ if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
+ continue;
+ }
+ if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Signal &&
+ (members & Signals) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Slot &&
+ (members & Slots) != 0) {
+ addMethod(method);
+ }
+ }
+ }
+
+ if ((members & Constructors) != 0) {
+ for (index = 0; index < prototype->constructorCount(); ++index)
+ addConstructor(prototype->constructor(index));
+ }
+
+ if ((members & Properties) != 0) {
+ for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
+ addProperty(prototype->property(index));
+ }
+
+ if ((members & Enumerators) != 0) {
+ for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
+ addEnumerator(prototype->enumerator(index));
+ }
+
+ if ((members & ClassInfos) != 0) {
+ for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
+ QMetaClassInfo ci = prototype->classInfo(index);
+ addClassInfo(ci.name(), ci.value());
+ }
+ }
+
+ if ((members & RelatedMetaObjects) != 0) {
+ const QMetaObject **objects;
+ if (priv(prototype->d.data)->revision < 2) {
+ objects = (const QMetaObject **)(prototype->d.extradata);
+ } else {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra)
+ objects = extra->objects;
+ else
+ objects = 0;
+ }
+ if (objects) {
+ while (*objects != 0) {
+ addRelatedMetaObject(*objects);
+ ++objects;
+ }
+ }
+ }
+
+ if ((members & StaticMetacall) != 0) {
+ if (priv(prototype->d.data)->revision >= 2) {
+ const QMetaObjectExtraData *extra =
+ (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra && extra->static_metacall)
+ setStaticMetacallFunction(extra->static_metacall);
+ }
+ }
+}
+
+/*!
+ Returns the method at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
+{
+ if (index >= 0 && index < d->methods.size())
+ return QMetaMethodBuilder(this, index);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the constructor at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
+{
+ if (index >= 0 && index < d->constructors.size())
+ return QMetaMethodBuilder(this, -(index + 1));
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the property at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
+{
+ if (index >= 0 && index < d->properties.size())
+ return QMetaPropertyBuilder(this, index);
+ else
+ return QMetaPropertyBuilder();
+}
+
+/*!
+ Returns the enumerator at \a index in this class.
+
+ \sa enumeratorCount(), addEnumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
+{
+ if (index >= 0 && index < d->enumerators.size())
+ return QMetaEnumBuilder(this, index);
+ else
+ return QMetaEnumBuilder();
+}
+
+/*!
+ Returns the related meta object at \a index in this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ return d->relatedMetaObjects[index];
+ else
+ return 0;
+}
+
+/*!
+ Returns the name of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoValue()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoName(int index) const
+{
+ if (index >= 0 && index < d->classInfoNames.size())
+ return d->classInfoNames[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoValue(int index) const
+{
+ if (index >= 0 && index < d->classInfoValues.size())
+ return d->classInfoValues[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Removes the method at \a index from this class. The indices of
+ all following methods will be adjusted downwards by 1. If the
+ method is registered as a notify signal on a property, then the
+ notify signal will be removed from the property.
+
+ \sa methodCount(), addMethod(), method(), indexOfMethod()
+*/
+void QMetaObjectBuilder::removeMethod(int index)
+{
+ if (index >= 0 && index < d->methods.size()) {
+ d->methods.removeAt(index);
+ for (int prop = 0; prop < d->properties.size(); ++prop) {
+ // Adjust the indices of property notify signal references.
+ if (d->properties[prop].notifySignal == index)
+ d->properties[prop].notifySignal = -1;
+ else if (d->properties[prop].notifySignal > index)
+ (d->properties[prop].notifySignal)--;
+ }
+ }
+}
+
+/*!
+ Removes the constructor at \a index from this class. The indices of
+ all following constructors will be adjusted downwards by 1.
+
+ \sa constructorCount(), addConstructor(), constructor()
+ \sa indexOfConstructor()
+*/
+void QMetaObjectBuilder::removeConstructor(int index)
+{
+ if (index >= 0 && index < d->constructors.size())
+ d->constructors.removeAt(index);
+}
+
+/*!
+ Removes the property at \a index from this class. The indices of
+ all following properties will be adjusted downwards by 1.
+
+ \sa propertyCount(), addProperty(), property(), indexOfProperty()
+*/
+void QMetaObjectBuilder::removeProperty(int index)
+{
+ if (index >= 0 && index < d->properties.size())
+ d->properties.removeAt(index);
+}
+
+/*!
+ Removes the enumerator at \a index from this class. The indices of
+ all following enumerators will be adjusted downwards by 1.
+
+ \sa enumeratorCount(), addEnumerator(), enumerator()
+ \sa indexOfEnumerator()
+*/
+void QMetaObjectBuilder::removeEnumerator(int index)
+{
+ if (index >= 0 && index < d->enumerators.size())
+ d->enumerators.removeAt(index);
+}
+
+/*!
+ Removes the item of class information at \a index from this class.
+ The indices of all following items will be adjusted downwards by 1.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName()
+ \sa classInfoValue() indexOfClassInfo()
+*/
+void QMetaObjectBuilder::removeClassInfo(int index)
+{
+ if (index >= 0 && index < d->classInfoNames.size()) {
+ d->classInfoNames.removeAt(index);
+ d->classInfoValues.removeAt(index);
+ }
+}
+
+/*!
+ Removes the related meta object at \a index from this class.
+ The indices of all following related meta objects will be adjusted
+ downwards by 1.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa relatedMetaObject()
+*/
+void QMetaObjectBuilder::removeRelatedMetaObject(int index)
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ d->relatedMetaObjects.removeAt(index);
+}
+
+/*!
+ Finds a method with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa method(), methodCount(), addMethod(), removeMethod()
+*/
+int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a signal with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSlot()
+*/
+int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Signal)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a slot with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSignal()
+*/
+int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Slot)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a constructor with the specified \a signature and returns its
+ index; otherwise returns -1. The \a signature will be normalized by
+ this method.
+
+ \sa constructor(), constructorCount(), addConstructor()
+ \sa removeConstructor()
+*/
+int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->constructors.size(); ++index) {
+ if (sig == d->constructors[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a property with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa property(), propertyCount(), addProperty(), removeProperty()
+*/
+int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
+{
+ for (int index = 0; index < d->properties.size(); ++index) {
+ if (name == d->properties[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an enumerator with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa enumerator(), enumeratorCount(), addEnumerator()
+ \sa removeEnumerator()
+*/
+int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
+{
+ for (int index = 0; index < d->enumerators.size(); ++index) {
+ if (name == d->enumerators[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an item of class information with the specified \a name and
+ returns its index; otherwise returns -1.
+
+ \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
+ \sa removeClassInfo()
+*/
+int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
+{
+ for (int index = 0; index < d->classInfoNames.size(); ++index) {
+ if (name == d->classInfoNames[index])
+ return index;
+ }
+ return -1;
+}
+
+// Align on a specific type boundary.
+#define ALIGN(size,type) \
+ (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
+
+// Build a string into a QMetaObject representation. Returns the
+// position in the string table where the string was placed.
+static int buildString
+ (char *buf, char *str, int *offset, const QByteArray& value, int empty)
+{
+ if (value.size() == 0 && empty >= 0)
+ return empty;
+ if (buf) {
+ memcpy(str + *offset, value.constData(), value.size());
+ str[*offset + value.size()] = '\0';
+ }
+ int posn = *offset;
+ *offset += value.size() + 1;
+ return posn;
+}
+
+// Build the parameter array string for a method.
+static QByteArray buildParameterNames
+ (const QByteArray& signature, const QList<QByteArray>& parameterNames)
+{
+ // If the parameter name list is specified, then concatenate them.
+ if (!parameterNames.isEmpty()) {
+ QByteArray names;
+ bool first = true;
+ foreach (QByteArray name, parameterNames) {
+ if (first)
+ first = false;
+ else
+ names += (char)',';
+ names += name;
+ }
+ return names;
+ }
+
+ // Count commas in the signature, excluding those inside template arguments.
+ int index = signature.indexOf('(');
+ if (index < 0)
+ return QByteArray();
+ ++index;
+ if (index >= signature.size())
+ return QByteArray();
+ if (signature[index] == ')')
+ return QByteArray();
+ int count = 1;
+ int brackets = 0;
+ while (index < signature.size() && signature[index] != ',') {
+ char ch = signature[index++];
+ if (ch == '<')
+ ++brackets;
+ else if (ch == '>')
+ --brackets;
+ else if (ch == ',' && brackets <= 0)
+ ++count;
+ }
+ return QByteArray(count - 1, ',');
+}
+
+// Build a QMetaObject in "buf" based on the information in "d".
+// If "buf" is null, then return the number of bytes needed to
+// build the QMetaObject.
+static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
+{
+ int size = 0;
+ int dataIndex;
+ int enumIndex;
+ int index;
+ bool hasNotifySignals = false;
+
+ // Create the main QMetaObject structure at the start of the buffer.
+ QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
+ size += sizeof(QMetaObject);
+ ALIGN(size, int);
+ if (buf) {
+ meta->d.superdata = d->superClass;
+ meta->d.extradata = 0;
+ }
+
+ // Populate the QMetaObjectPrivate structure.
+ QMetaObjectPrivate *pmeta
+ = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
+ dataIndex = 13; // Number of fields in the QMetaObjectPrivate.
+ for (index = 0; index < d->properties.size(); ++index) {
+ if (d->properties[index].notifySignal != -1) {
+ hasNotifySignals = true;
+ break;
+ }
+ }
+ if (buf) {
+ pmeta->revision = 3;
+ pmeta->flags = d->flags;
+ pmeta->className = 0; // Class name is always the first string.
+
+ pmeta->classInfoCount = d->classInfoNames.size();
+ pmeta->classInfoData = dataIndex;
+ dataIndex += 2 * d->classInfoNames.size();
+
+ pmeta->methodCount = d->methods.size();
+ pmeta->methodData = dataIndex;
+ dataIndex += 5 * d->methods.size();
+
+ pmeta->propertyCount = d->properties.size();
+ pmeta->propertyData = dataIndex;
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+
+ pmeta->enumeratorCount = d->enumerators.size();
+ pmeta->enumeratorData = dataIndex;
+ dataIndex += 4 * d->enumerators.size();
+
+ pmeta->constructorCount = d->constructors.size();
+ pmeta->constructorData = dataIndex;
+ dataIndex += 5 * d->constructors.size();
+ } else {
+ dataIndex += 2 * d->classInfoNames.size();
+ dataIndex += 5 * d->methods.size();
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+ dataIndex += 4 * d->enumerators.size();
+ dataIndex += 5 * d->constructors.size();
+ }
+
+ // Allocate space for the enumerator key names and values.
+ enumIndex = dataIndex;
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ dataIndex += 2 * enumerator->keys.size();
+ }
+
+ // Zero terminator at the end of the data offset table.
+ ++dataIndex;
+
+ // Find the start of the data and string tables.
+ int *data = reinterpret_cast<int *>(pmeta);
+ size += dataIndex * sizeof(int);
+ char *str = reinterpret_cast<char *>(buf + size);
+ if (buf) {
+ meta->d.stringdata = str;
+ meta->d.data = reinterpret_cast<uint *>(data);
+ }
+
+ // Reset the current data position to just past the QMetaObjectPrivate.
+ dataIndex = 13;
+
+ // Add the class name to the string table.
+ int offset = 0;
+ buildString(buf, str, &offset, d->className, -1);
+
+ // Add a common empty string, which is used to indicate "void"
+ // method returns, empty tag strings, etc.
+ int empty = buildString(buf, str, &offset, QByteArray(), -1);
+
+ // Output the class infos,
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ int name = buildString(buf, str, &offset, d->classInfoNames[index], empty);
+ int value = buildString(buf, str, &offset, d->classInfoValues[index], empty);
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = value;
+ }
+ dataIndex += 2;
+ }
+
+ // Output the methods in the class.
+ for (index = 0; index < d->methods.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // Output the properties in the class.
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ int name = buildString(buf, str, &offset, prop->name, empty);
+ int type = buildString(buf, str, &offset, prop->type, empty);
+ int flags = prop->flags;
+
+ if (!isVariantType(prop->type)) {
+ flags |= EnumOrFlag;
+ } else {
+ flags |= qvariant_nameToType(prop->type) << 24;
+ }
+
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = type;
+ data[dataIndex + 2] = flags;
+ }
+ dataIndex += 3;
+ }
+ if (hasNotifySignals) {
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ if (buf) {
+ if (prop->notifySignal != -1)
+ data[dataIndex] = prop->notifySignal;
+ else
+ data[dataIndex] = 0;
+ }
+ ++dataIndex;
+ }
+ }
+
+ // Output the enumerators in the class.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ int name = buildString(buf, str, &offset, enumerator->name, empty);
+ int isFlag = (int)(enumerator->isFlag);
+ int count = enumerator->keys.size();
+ int enumOffset = enumIndex;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = isFlag;
+ data[dataIndex + 2] = count;
+ data[dataIndex + 3] = enumOffset;
+ }
+ for (int key = 0; key < count; ++key) {
+ int keyIndex = buildString(buf, str, &offset, enumerator->keys[key], empty);
+ if (buf) {
+ data[enumOffset++] = keyIndex;
+ data[enumOffset++] = enumerator->values[key];
+ }
+ }
+ dataIndex += 4;
+ enumIndex += 2 * count;
+ }
+
+ // Output the constructors in the class.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // One more empty string to act as a terminator.
+ buildString(buf, str, &offset, QByteArray(), -1);
+ size += offset;
+
+ // Output the zero terminator in the data array.
+ if (buf)
+ data[enumIndex] = 0;
+
+ // Create the extradata block if we need one.
+ if (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction) {
+ ALIGN(size, QMetaObject **);
+ ALIGN(size, QMetaObjectBuilder::StaticMetacallFunction);
+ QMetaObjectExtraData *extra =
+ reinterpret_cast<QMetaObjectExtraData *>(buf + size);
+ size += sizeof(QMetaObjectExtraData);
+ ALIGN(size, QMetaObject *);
+ const QMetaObject **objects =
+ reinterpret_cast<const QMetaObject **>(buf + size);
+ if (buf) {
+ if (d->relatedMetaObjects.size() > 0) {
+ extra->objects = objects;
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index)
+ objects[index] = d->relatedMetaObjects[index];
+ objects[index] = 0;
+ } else {
+ extra->objects = 0;
+ }
+ extra->static_metacall = d->staticMetacallFunction;
+ meta->d.extradata = reinterpret_cast<void *>(extra);
+ }
+ if (d->relatedMetaObjects.size() > 0)
+ size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1);
+ }
+
+ // Align the final size and return it.
+ ALIGN(size, void *);
+ return size;
+}
+
+/*!
+ Converts this meta object builder into a concrete QMetaObject.
+ The return value should be deallocated using qFree() once it
+ is no longer needed.
+
+ The returned meta object is a snapshot of the state of the
+ QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
+ will not be reflected in previous meta objects returned by
+ this method.
+*/
+QMetaObject *QMetaObjectBuilder::toMetaObject() const
+{
+ int size = buildMetaObject(d, 0);
+ char *buf = reinterpret_cast<char *>(qMalloc(size));
+ buildMetaObject(d, buf);
+ return reinterpret_cast<QMetaObject *>(buf);
+}
+
+/*!
+ \typedef QMetaObjectBuilder::StaticMetacallFunction
+
+ Typedef for static metacall functions. The three parameters are
+ the call type value, the constructor index, and the
+ array of parameters.
+*/
+
+/*!
+ Returns the static metacall function to use to construct objects
+ of this class. The default value is null.
+
+ \sa setStaticMetacallFunction()
+*/
+QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
+{
+ return d->staticMetacallFunction;
+}
+
+/*!
+ Sets the static metacall function to use to construct objects
+ of this class to \a value. The default value is null.
+
+ \sa staticMetacallFunction()
+*/
+void QMetaObjectBuilder::setStaticMetacallFunction
+ (QMetaObjectBuilder::StaticMetacallFunction value)
+{
+ d->staticMetacallFunction = value;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ Serializes the contents of the meta object builder onto \a stream.
+
+ \sa deserialize()
+*/
+void QMetaObjectBuilder::serialize(QDataStream& stream) const
+{
+ int index;
+
+ // Write the class and super class names.
+ stream << d->className;
+ if (d->superClass)
+ stream << QByteArray(d->superClass->className());
+ else
+ stream << QByteArray();
+
+ // Write the counts for each type of class member.
+ stream << d->classInfoNames.size();
+ stream << d->methods.size();
+ stream << d->properties.size();
+ stream << d->enumerators.size();
+ stream << d->constructors.size();
+ stream << d->relatedMetaObjects.size();
+
+ // Write the items of class information.
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ stream << d->classInfoNames[index];
+ stream << d->classInfoValues[index];
+ }
+
+ // Write the methods.
+ for (index = 0; index < d->methods.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the properties.
+ for (index = 0; index < d->properties.size(); ++index) {
+ const QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream << property->name;
+ stream << property->type;
+ stream << property->flags;
+ stream << property->notifySignal;
+ }
+
+ // Write the enumerators.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ const QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream << enumerator->name;
+ stream << enumerator->isFlag;
+ stream << enumerator->keys;
+ stream << enumerator->values;
+ }
+
+ // Write the constructors.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the related meta objects.
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
+ const QMetaObject *meta = d->relatedMetaObjects[index];
+ stream << QByteArray(meta->className());
+ }
+
+ // Add an extra empty QByteArray for additional data in future versions.
+ // This should help maintain backwards compatibility, allowing older
+ // versions to read newer data.
+ stream << QByteArray();
+}
+
+// Resolve a class name using the name reference map.
+static const QMetaObject *resolveClassName
+ (const QMap<QByteArray, const QMetaObject *>& references,
+ const QByteArray& name)
+{
+ if (name == QByteArray("QObject"))
+ return &QObject::staticMetaObject;
+ else
+ return references.value(name, 0);
+}
+
+/*!
+ Deserializes a meta object builder from \a stream into
+ this meta object builder.
+
+ The \a references parameter specifies a mapping from class names
+ to QMetaObject instances for resolving the super class name and
+ related meta objects in the object that is deserialized.
+ The meta object for QObject is implicitly added to \a references
+ and does not need to be supplied.
+
+ The QDataStream::status() value on \a stream will be set to
+ QDataStream::ReadCorruptData if the input data is corrupt.
+ The status will be set to QDataStream::ReadPastEnd if the
+ input was exhausted before the full meta object was read.
+
+ \sa serialize()
+*/
+void QMetaObjectBuilder::deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references)
+{
+ QByteArray name;
+ const QMetaObject *cl;
+ int index;
+
+ // Clear all members in the builder to their default states.
+ d->className.clear();
+ d->superClass = &QObject::staticMetaObject;
+ d->classInfoNames.clear();
+ d->classInfoValues.clear();
+ d->methods.clear();
+ d->properties.clear();
+ d->enumerators.clear();
+ d->constructors.clear();
+ d->relatedMetaObjects.clear();
+ d->staticMetacallFunction = 0;
+
+ // Read the class and super class names.
+ stream >> d->className;
+ stream >> name;
+ if (name.isEmpty()) {
+ d->superClass = 0;
+ } else if ((cl = resolveClassName(references, name)) != 0) {
+ d->superClass = cl;
+ } else {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the counts for each type of class member.
+ int classInfoCount, methodCount, propertyCount;
+ int enumeratorCount, constructorCount, relatedMetaObjectCount;
+ stream >> classInfoCount;
+ stream >> methodCount;
+ stream >> propertyCount;
+ stream >> enumeratorCount;
+ stream >> constructorCount;
+ stream >> relatedMetaObjectCount;
+ if (classInfoCount < 0 || methodCount < 0 ||
+ propertyCount < 0 || enumeratorCount < 0 ||
+ constructorCount < 0 || relatedMetaObjectCount < 0) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the items of class information.
+ for (index = 0; index < classInfoCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray value;
+ stream >> name;
+ stream >> value;
+ addClassInfo(name, value);
+ }
+
+ // Read the member methods.
+ for (index = 0; index < methodCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addMethod(name);
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() == QMetaMethod::Constructor) {
+ // Cannot add a constructor in this set of methods.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the properties.
+ for (index = 0; index < propertyCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray type;
+ stream >> name;
+ stream >> type;
+ addProperty(name, type);
+ QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream >> property->flags;
+ stream >> property->notifySignal;
+ if (property->notifySignal < -1 ||
+ property->notifySignal >= d->methods.size()) {
+ // Notify signal method index is out of range.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ if (property->notifySignal >= 0 &&
+ d->methods[property->notifySignal].methodType() != QMetaMethod::Signal) {
+ // Notify signal method index does not refer to a signal.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the enumerators.
+ for (index = 0; index < enumeratorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addEnumerator(name);
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream >> enumerator->isFlag;
+ stream >> enumerator->keys;
+ stream >> enumerator->values;
+ if (enumerator->keys.size() != enumerator->values.size()) {
+ // Mismatch between number of keys and number of values.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the constructor methods.
+ for (index = 0; index < constructorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addConstructor(name);
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() != QMetaMethod::Constructor) {
+ // The type must be Constructor.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the related meta objects.
+ for (index = 0; index < relatedMetaObjectCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ cl = resolveClassName(references, name);
+ if (!cl) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ addRelatedMetaObject(cl);
+ }
+
+ // Read the extra data block, which is reserved for future use.
+ stream >> name;
+}
+
+#endif // !QT_NO_DATASTREAM
+
+/*!
+ \class QMetaMethodBuilder
+ \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
+*/
+
+QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
+{
+ // Positive indices indicate methods, negative indices indicate constructors.
+ if (_mobj && _index >= 0 && _index < _mobj->d->methods.size())
+ return &(_mobj->d->methods[_index]);
+ else if (_mobj && -_index >= 1 && -_index <= _mobj->d->constructors.size())
+ return &(_mobj->d->constructors[(-_index) - 1]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaMethodBuilder::QMetaMethodBuilder()
+ \internal
+*/
+
+/*!
+ Returns the index of this method within its QMetaObjectBuilder.
+*/
+int QMetaMethodBuilder::index() const
+{
+ if (_index >= 0)
+ return _index; // Method, signal, or slot
+ else
+ return (-_index) - 1; // Constructor
+}
+
+/*!
+ Returns the type of this method (signal, slot, method, or constructor).
+*/
+QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->methodType();
+ else
+ return QMetaMethod::Method;
+}
+
+/*!
+ Returns the signature of this method.
+
+ \sa parameterNames(), returnType()
+*/
+QByteArray QMetaMethodBuilder::signature() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->signature;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the return type for this method; empty if the method's
+ return type is \c{void}.
+
+ \sa setReturnType(), signature()
+*/
+QByteArray QMetaMethodBuilder::returnType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->returnType;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the return type for this method to \a value. If \a value
+ is empty, then the method's return type is \c{void}. The \a value
+ will be normalized before it is added to the method.
+
+ \sa returnType(), signature()
+*/
+void QMetaMethodBuilder::setReturnType(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->returnType = QMetaObject::normalizedType(value);
+}
+
+/*!
+ Returns the list of parameter names for this method.
+
+ \sa setParameterNames()
+*/
+QList<QByteArray> QMetaMethodBuilder::parameterNames() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->parameterNames;
+ else
+ return QList<QByteArray>();
+}
+
+/*!
+ Sets the list of parameter names for this method to \a value.
+
+ \sa parameterNames()
+*/
+void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->parameterNames = value;
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ \sa setTag()
+*/
+QByteArray QMetaMethodBuilder::tag() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->tag;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the tag associated with this method to \a value.
+
+ \sa tag()
+*/
+void QMetaMethodBuilder::setTag(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->tag = value;
+}
+
+/*!
+ Returns the access specification of this method (private, protected,
+ or public). The default value is QMetaMethod::Public for methods,
+ slots, and constructors. The default value is QMetaMethod::Protected
+ for signals.
+
+ \sa setAccess()
+*/
+QMetaMethod::Access QMetaMethodBuilder::access() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->access();
+ else
+ return QMetaMethod::Public;
+}
+
+/*!
+ Sets the access specification of this method (private, protected,
+ or public) to \a value. If the method is a signal, this function
+ will be ignored.
+
+ \sa access()
+*/
+void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d && d->methodType() != QMetaMethod::Signal)
+ d->setAccess(value);
+}
+
+/*!
+ Returns the additional attributes for this method.
+
+ \sa setAttributes()
+*/
+int QMetaMethodBuilder::attributes() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return (d->attributes >> 4);
+ else
+ return 0;
+}
+
+/*!
+ Sets the additional attributes for this method to \a value.
+
+ \sa attributes()
+*/
+void QMetaMethodBuilder::setAttributes(int value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->attributes = ((d->attributes & 0x0f) | (value << 4));
+}
+
+/*!
+ \class QMetaPropertyBuilder
+ \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
+*/
+
+QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->properties.size())
+ return &(_mobj->d->properties[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaPropertyBuilder::index() const
+
+ Returns the index of this property within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name associated with this property.
+
+ \sa type()
+*/
+QByteArray QMetaPropertyBuilder::name() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the type associated with this property.
+
+ \sa name()
+*/
+QByteArray QMetaPropertyBuilder::type() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->type;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this property has a notify signal; false otherwise.
+
+ \sa notifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+bool QMetaPropertyBuilder::hasNotifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Notify);
+ else
+ return false;
+}
+
+/*!
+ Returns the notify signal associated with this property.
+
+ \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d && d->notifySignal >= 0)
+ return QMetaMethodBuilder(_mobj, d->notifySignal);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Sets the notify signal associated with this property to \a value.
+
+ \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
+*/
+void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ if (value._mobj) {
+ d->notifySignal = value._index;
+ d->setFlag(Notify, true);
+ } else {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+ }
+}
+
+/*!
+ Removes the notify signal from this property.
+
+ \sa hasNotifySignal(), notifySignal(), setNotifySignal()
+*/
+void QMetaPropertyBuilder::removeNotifySignal()
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+ The default value is true.
+
+ \sa setReadable(), isWritable()
+*/
+bool QMetaPropertyBuilder::isReadable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Readable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns false.
+ The default value is true.
+
+ \sa setWritable(), isReadable()
+*/
+bool QMetaPropertyBuilder::isWritable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Writable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false. The default value is false.
+
+ \sa setResettable()
+*/
+bool QMetaPropertyBuilder::isResettable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Resettable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designable; otherwise returns false.
+ This default value is false.
+
+ \sa setDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isDesignable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Designable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is scriptable; otherwise returns false.
+ This default value is false.
+
+ \sa setScriptable(), isDesignable(), isStored()
+*/
+bool QMetaPropertyBuilder::isScriptable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Scriptable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is stored; otherwise returns false.
+ This default value is false.
+
+ \sa setStored(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isStored() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Stored);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is editable; otherwise returns false.
+ This default value is false.
+
+ \sa setEditable(), isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isEditable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Editable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit or that is
+ significant in some other way. Otherwise it returns
+ false. This default value is false.
+
+ \sa setUser(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isUser() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(User);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern. The default value is false.
+
+ \sa setStdCppSet()
+*/
+bool QMetaPropertyBuilder::hasStdCppSet() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(StdCppSet);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is an enumerator or flag type;
+ otherwise returns false. This default value is false.
+
+ \sa setEnumOrFlag()
+*/
+bool QMetaPropertyBuilder::isEnumOrFlag() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(EnumOrFlag);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has the dynamic flag set;
+ otherwise returns false. The default value is false.
+
+ \sa setDynamic()
+*/
+bool QMetaPropertyBuilder::isDynamic() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Dynamic);
+ else
+ return false;
+}
+
+/*!
+ Sets this property to readable if \a value is true.
+
+ \sa isReadable(), setWritable()
+*/
+void QMetaPropertyBuilder::setReadable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Readable, value);
+}
+
+/*!
+ Sets this property to writable if \a value is true.
+
+ \sa isWritable(), setReadable()
+*/
+void QMetaPropertyBuilder::setWritable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Writable, value);
+}
+
+/*!
+ Sets this property to resettable if \a value is true.
+
+ \sa isResettable()
+*/
+void QMetaPropertyBuilder::setResettable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Resettable, value);
+}
+
+/*!
+ Sets this property to designable if \a value is true.
+
+ \sa isDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setDesignable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Designable, value);
+}
+
+/*!
+ Sets this property to scriptable if \a value is true.
+
+ \sa isScriptable(), setDesignable(), setStored()
+*/
+void QMetaPropertyBuilder::setScriptable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Scriptable, value);
+}
+
+/*!
+ Sets this property to storable if \a value is true.
+
+ \sa isStored(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setStored(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Stored, value);
+}
+
+/*!
+ Sets this property to editable if \a value is true.
+
+ \sa isEditable(), setDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setEditable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Editable, value);
+}
+
+/*!
+ Sets the \c USER flag on this property to \a value.
+
+ \sa isUser(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setUser(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(User, value);
+}
+
+/*!
+ Sets the C++ setter flag on this property to \a value, which is
+ true if the property has a C++ setter function that follows Qt's
+ standard "name" / "setName" pattern.
+
+ \sa hasStdCppSet()
+*/
+void QMetaPropertyBuilder::setStdCppSet(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(StdCppSet, value);
+}
+
+/*!
+ Sets this property to be of an enumerator or flag type if
+ \a value is true.
+
+ \sa isEnumOrFlag()
+*/
+void QMetaPropertyBuilder::setEnumOrFlag(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(EnumOrFlag, value);
+}
+
+/*!
+ Sets this property to have the dynamic flag if \a value is
+ true.
+
+ \sa isDynamic()
+*/
+void QMetaPropertyBuilder::setDynamic(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Dynamic, value);
+}
+
+/*!
+ \class QMetaEnumBuilder
+ \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
+*/
+
+QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->enumerators.size())
+ return &(_mobj->d->enumerators[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaEnumBuilder::QMetaEnumBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaEnumBuilder::index() const
+
+ Returns the index of this enumerator within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+*/
+QByteArray QMetaEnumBuilder::name() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ \sa setIsFlag()
+*/
+bool QMetaEnumBuilder::isFlag() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->isFlag;
+ else
+ return false;
+}
+
+/*!
+ Sets this enumerator to be used as a flag if \a value is true.
+
+ \sa isFlag()
+*/
+void QMetaEnumBuilder::setIsFlag(bool value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->isFlag = value;
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key(), addKey()
+*/
+int QMetaEnumBuilder::keyCount() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->keys.size();
+ else
+ return 0;
+}
+
+/*!
+ Returns the key with the given \a index, or an empty QByteArray
+ if no such key exists.
+
+ \sa keyCount(), addKey(), value()
+*/
+QByteArray QMetaEnumBuilder::key(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->keys[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), addKey(), key()
+*/
+int QMetaEnumBuilder::value(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->values[index];
+ else
+ return -1;
+}
+
+/*!
+ Adds a new key called \a name to this enumerator, associated
+ with \a value. Returns the index of the new key.
+
+ \sa keyCount(), key(), value(), removeKey()
+*/
+int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d) {
+ int index = d->keys.size();
+ d->keys += name;
+ d->values += value;
+ return index;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Removes the key at \a index from this enumerator.
+
+ \sa addKey()
+*/
+void QMetaEnumBuilder::removeKey(int index)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size()) {
+ d->keys.removeAt(index);
+ d->values.removeAt(index);
+ }
+}
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
new file mode 100644
index 0000000..dc95745
--- /dev/null
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECTBUILDER_H
+#define QMETAOBJECTBUILDER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmap.h>
+
+class QMetaObjectBuilderPrivate;
+class QMetaMethodBuilder;
+class QMetaMethodBuilderPrivate;
+class QMetaPropertyBuilder;
+class QMetaPropertyBuilderPrivate;
+class QMetaEnumBuilder;
+class QMetaEnumBuilderPrivate;
+
+class Q_CORE_EXPORT QMetaObjectBuilder
+{
+public:
+ enum AddMember
+ {
+ ClassName = 0x00000001,
+ SuperClass = 0x00000002,
+ Methods = 0x00000004,
+ Signals = 0x00000008,
+ Slots = 0x00000010,
+ Constructors = 0x00000020,
+ Properties = 0x00000040,
+ Enumerators = 0x00000080,
+ ClassInfos = 0x00000100,
+ RelatedMetaObjects = 0x00000200,
+ StaticMetacall = 0x00000400,
+ PublicMethods = 0x00000800,
+ ProtectedMethods = 0x00001000,
+ PrivateMethods = 0x00002000,
+ AllMembers = 0x7FFFFFFF,
+ AllPrimaryMembers = 0x7FFFFBFC
+ };
+ Q_DECLARE_FLAGS(AddMembers, AddMember)
+
+ enum MetaObjectFlag {
+ DynamicMetaObject = 0x01
+ };
+ Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
+
+ QMetaObjectBuilder();
+ explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+ virtual ~QMetaObjectBuilder();
+
+ QByteArray className() const;
+ void setClassName(const QByteArray& name);
+
+ const QMetaObject *superClass() const;
+ void setSuperClass(const QMetaObject *meta);
+
+ MetaObjectFlags flags() const;
+ void setFlags(MetaObjectFlags);
+
+ int methodCount() const;
+ int constructorCount() const;
+ int propertyCount() const;
+ int enumeratorCount() const;
+ int classInfoCount() const;
+ int relatedMetaObjectCount() const;
+
+ QMetaMethodBuilder addMethod(const QByteArray& signature);
+ QMetaMethodBuilder addMethod(const QByteArray& signature, const QByteArray& returnType);
+ QMetaMethodBuilder addMethod(const QMetaMethod& prototype);
+
+ QMetaMethodBuilder addSlot(const QByteArray& signature);
+ QMetaMethodBuilder addSignal(const QByteArray& signature);
+
+ QMetaMethodBuilder addConstructor(const QByteArray& signature);
+ QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
+
+ QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
+ QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
+
+ QMetaEnumBuilder addEnumerator(const QByteArray& name);
+ QMetaEnumBuilder addEnumerator(const QMetaEnum& prototype);
+
+ int addClassInfo(const QByteArray& name, const QByteArray& value);
+
+ int addRelatedMetaObject(const QMetaObject *meta);
+
+ void addMetaObject(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+
+ QMetaMethodBuilder method(int index) const;
+ QMetaMethodBuilder constructor(int index) const;
+ QMetaPropertyBuilder property(int index) const;
+ QMetaEnumBuilder enumerator(int index) const;
+ const QMetaObject *relatedMetaObject(int index) const;
+
+ QByteArray classInfoName(int index) const;
+ QByteArray classInfoValue(int index) const;
+
+ void removeMethod(int index);
+ void removeConstructor(int index);
+ void removeProperty(int index);
+ void removeEnumerator(int index);
+ void removeClassInfo(int index);
+ void removeRelatedMetaObject(int index);
+
+ int indexOfMethod(const QByteArray& signature);
+ int indexOfSignal(const QByteArray& signature);
+ int indexOfSlot(const QByteArray& signature);
+ int indexOfConstructor(const QByteArray& signature);
+ int indexOfProperty(const QByteArray& name);
+ int indexOfEnumerator(const QByteArray& name);
+ int indexOfClassInfo(const QByteArray& name);
+
+ typedef int (*StaticMetacallFunction)(QMetaObject::Call, int, void **);
+
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const;
+ void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
+
+ QMetaObject *toMetaObject() const;
+
+#ifndef QT_NO_DATASTREAM
+ void serialize(QDataStream& stream) const;
+ void deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references);
+#endif
+
+private:
+ Q_DISABLE_COPY(QMetaObjectBuilder);
+
+ QMetaObjectBuilderPrivate *d;
+
+ friend class QMetaMethodBuilder;
+ friend class QMetaPropertyBuilder;
+ friend class QMetaEnumBuilder;
+};
+
+class Q_CORE_EXPORT QMetaMethodBuilder
+{
+public:
+ QMetaMethodBuilder() : _mobj(0), _index(0) {}
+
+ int index() const;
+
+ QMetaMethod::MethodType methodType() const;
+ QByteArray signature() const;
+
+ QByteArray returnType() const;
+ void setReturnType(const QByteArray& value);
+
+ QList<QByteArray> parameterNames() const;
+ void setParameterNames(const QList<QByteArray>& value);
+
+ QByteArray tag() const;
+ void setTag(const QByteArray& value);
+
+ QMetaMethod::Access access() const;
+ void setAccess(QMetaMethod::Access value);
+
+ int attributes() const;
+ void setAttributes(int value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+ friend class QMetaPropertyBuilder;
+
+ QMetaMethodBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaMethodBuilderPrivate *d_func() const;
+};
+
+class Q_CORE_EXPORT QMetaPropertyBuilder
+{
+public:
+ QMetaPropertyBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+ QByteArray type() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethodBuilder notifySignal() const;
+ void setNotifySignal(const QMetaMethodBuilder& value);
+ void removeNotifySignal();
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable() const;
+ bool isScriptable() const;
+ bool isStored() const;
+ bool isEditable() const;
+ bool isUser() const;
+ bool hasStdCppSet() const;
+ bool isEnumOrFlag() const;
+ bool isDynamic() const;
+
+ void setReadable(bool value);
+ void setWritable(bool value);
+ void setResettable(bool value);
+ void setDesignable(bool value);
+ void setScriptable(bool value);
+ void setStored(bool value);
+ void setEditable(bool value);
+ void setUser(bool value);
+ void setStdCppSet(bool value);
+ void setEnumOrFlag(bool value);
+ void setDynamic(bool value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaPropertyBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaPropertyBuilderPrivate *d_func() const;
+};
+
+class Q_CORE_EXPORT QMetaEnumBuilder
+{
+public:
+ QMetaEnumBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+
+ bool isFlag() const;
+ void setIsFlag(bool value);
+
+ int keyCount() const;
+ QByteArray key(int index) const;
+ int value(int index) const;
+
+ int addKey(const QByteArray& name, int value);
+ void removeKey(int index);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaEnumBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaEnumBuilderPrivate *d_func() const;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::MetaObjectFlags)
+
+#endif
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 543422c..f3a8438 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -143,10 +143,12 @@ QObjectPrivate::QObjectPrivate(int version)
inEventHandler = false;
inThreadChangeEvent = false;
deleteWatch = 0;
+ metaObject = 0;
}
QObjectPrivate::~QObjectPrivate()
{
+ delete static_cast<QAbstractDynamicMetaObject*>(metaObject);
if (deleteWatch)
*deleteWatch = 1;
#ifndef QT_NO_USERDATA
@@ -451,7 +453,7 @@ QMetaCallEvent::~QMetaCallEvent()
*/
int QMetaCallEvent::placeMetaCall(QObject *object)
{
- return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_);
+ return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_);
}
/*!
@@ -811,6 +813,14 @@ QObject::~QObject()
d->eventFilters.clear();
+ // As declarativeData is in a union with currentChildBeingDeleted, this must
+ // be done (and declarativeData set back to 0) before deleting children.
+ if(d->declarativeData) {
+ QDeclarativeData *dd = d->declarativeData;
+ d->declarativeData = 0;
+ dd->destroyed(this);
+ }
+
if (!d->children.isEmpty())
d->deleteChildren();
@@ -3089,10 +3099,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
}
#if defined(QT_NO_EXCEPTIONS)
- receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
#else
try {
- receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
} catch (...) {
locker.relock();
@@ -3796,6 +3806,7 @@ void qDeleteInEventHandler(QObject *o)
delete o;
}
+
QT_END_NAMESPACE
#include "moc_qobject.cpp"
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index dbec0a6..b6bdfb3 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -108,6 +108,7 @@ public:
uint inThreadChangeEvent : 1;
uint unused : 23;
int postedEvents;
+ QMetaObject *metaObject; // assert dynamic
};
@@ -378,6 +379,9 @@ inline QList<T> qFindChildren(const QObject *o, const QRegExp &re)
#endif // Q_MOC_RUN
+template <class T> inline const char * qobject_interface_iid()
+{ return 0; }
+
template <class T> inline T qobject_cast_helper(QObject *object, T)
{ return static_cast<T>(((T)0)->staticMetaObject.cast(object)); }
@@ -394,6 +398,8 @@ inline T qobject_cast(const QObject *object)
#ifndef Q_MOC_RUN
# define Q_DECLARE_INTERFACE(IFace, IId) \
+ template <> inline const char *qobject_interface_iid<IFace *>() \
+ { return IId; } \
template <> inline IFace *qobject_cast_helper<IFace *>(QObject *object, IFace *) \
{ return (IFace *)(object ? object->qt_metacast(IId) : 0); } \
template <> inline IFace *qobject_cast_helper<IFace *>(const QObject *object, IFace *) \
@@ -457,8 +463,13 @@ inline T qobject_cast(const QObject *object)
}
+template <class T> inline const char * qobject_interface_iid()
+{ return 0; }
+
#ifndef Q_MOC_RUN
# define Q_DECLARE_INTERFACE(IFace, IId) \
+ template <> inline const char *qobject_interface_iid<IFace *>() \
+ { return IId; } \
template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
{ return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \
template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 96d79af..bc7995c 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -85,6 +85,13 @@ inline QObjectData::~QObjectData() {}
enum { QObjectPrivateVersion = QT_VERSION };
+class Q_CORE_EXPORT QDeclarativeData
+{
+public:
+ virtual ~QDeclarativeData() {}
+ virtual void destroyed(QObject *) {}
+};
+
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
Q_DECLARE_PUBLIC(QObject)
@@ -117,7 +124,10 @@ public:
// object currently activating the object
Sender *currentSender;
- QObject *currentChildBeingDeleted;
+ union {
+ QObject *currentChildBeingDeleted;
+ QDeclarativeData *declarativeData;
+ };
bool isSender(const QObject *receiver, const char *signal) const;
QObjectList receiverList(const char *signal) const;
@@ -217,6 +227,14 @@ private:
void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
+
+struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject
+{
+ virtual ~QAbstractDynamicMetaObject() {}
+ virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; }
+ virtual int createProperty(const char *, const char *) { return -1; }
+};
+
QT_END_NAMESPACE
#endif // QOBJECT_P_H
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 3a22323..98cc108 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -77,6 +77,7 @@ class QString;
#endif
#define Q_CLASSINFO(name, value)
#define Q_INTERFACES(x)
+#define Q_CAST_INTERFACES(x)
#define Q_PROPERTY(text)
#define Q_OVERRIDE(text)
#define Q_ENUMS(x)
@@ -169,6 +170,7 @@ private:
#define Q_SIGNALS Q_SIGNALS
#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value)
#define Q_INTERFACES(x) Q_INTERFACES(x)
+#define Q_CAST_INTERFACES(x) Q_CAST_INTERFACES(x)
#define Q_PROPERTY(text) Q_PROPERTY(text)
#define Q_OVERRIDE(text) Q_OVERRIDE(text)
#define Q_ENUMS(x) Q_ENUMS(x)
@@ -428,6 +430,7 @@ struct Q_CORE_EXPORT QMetaObject
};
int static_metacall(Call, int, void **) const;
+ static int metacall(QObject *, Call, int, void **);
#ifdef QT3_SUPPORT
QT3_SUPPORT const char *superClassName() const;
@@ -439,6 +442,7 @@ struct Q_CORE_EXPORT QMetaObject
const uint *data;
const void *extradata;
} d;
+
};
struct QMetaObjectExtraData
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 033b760..074575b 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -134,7 +134,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
template <class T>
inline void v_clear(QVariant::Private *d, T* = 0)
{
-
+
if (sizeof(T) > sizeof(QVariant::Private::Data)) {
//now we need to cast
//because QVariant::PrivateShared doesn't have a virtual destructor
diff --git a/src/declarative/3rdparty/3rdparty.pri b/src/declarative/3rdparty/3rdparty.pri
new file mode 100644
index 0000000..fc78cb2
--- /dev/null
+++ b/src/declarative/3rdparty/3rdparty.pri
@@ -0,0 +1,5 @@
+HEADERS += \
+ 3rdparty/qlistmodelinterface.h\
+
+SOURCES += \
+ 3rdparty/qlistmodelinterface.cpp \
diff --git a/src/declarative/3rdparty/qlistmodelinterface.cpp b/src/declarative/3rdparty/qlistmodelinterface.cpp
new file mode 100644
index 0000000..75960a1
--- /dev/null
+++ b/src/declarative/3rdparty/qlistmodelinterface.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlistmodelinterface.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QListModelInterface
+ \brief The QListModelInterface class can be subclassed to provide C++ models to QFx Views
+
+ This class is comprised primarily of pure virtual functions which
+ you must implement in a subclass. You can then use the subclass
+ as a model for a QFx view, such as a QFxListView.
+*/
+
+/*! \fn QListModelInterface::QListModelInterface(QObject *parent)
+ Constructs a QListModelInterface with the specified \a parent.
+*/
+
+ /*! \fn QListModelInterface::QListModelInterface(QObjectPrivate &dd, QObject *parent)
+
+ \internal
+ */
+
+/*! \fn QListModelInterface::~QListModelInterface()
+ The destructor is virtual.
+ */
+
+/*! \fn int QListModelInterface::count() const
+ Returns the number of data entries in the model.
+*/
+
+/*! \fn QHash<int,QVariant> QListModelInterface::data(int index, const QList<int>& roles) const
+ Returns the data at the given \a index for the specifed \a roles.
+*/
+
+/*! \fn bool QListModelInterface::setData(int index, const QHash<int,QVariant>& values)
+ Sets the data at the given \a index. \a values is a mapping of
+ QVariant values to roles. Returns false.
+*/
+
+/*! \fn QList<int> QListModelInterface::roles() const
+ Returns the list of roles for which the list model interface
+ provides data.
+*/
+
+/*! \fn QString QListModelInterface::toString(int role) const
+ Returns a string description of the specified \a role.
+*/
+
+/*! \fn void QListModelInterface::itemsInserted(int index, int count)
+ Emit this signal when \a count items are inserted at \a index.
+ */
+
+/*! \fn void QListModelInterface::itemsRemoved(int index, int count)
+ Emit this signal when \a count items are removed at \a index.
+ */
+
+/*! \fn void QListModelInterface::itemsMoved(int from, int to, int count)
+ Emit this signal when \a count items are moved from index \a from
+ to index \a to.
+ */
+
+/*! \fn void QListModelInterface::itemsChanged(int index, int count, const QList<int> &roles)
+ Emit this signal when \a count items at \a index have had their
+ \a roles changed.
+ */
+
+QT_END_NAMESPACE
diff --git a/src/declarative/3rdparty/qlistmodelinterface.h b/src/declarative/3rdparty/qlistmodelinterface.h
new file mode 100644
index 0000000..44c4a24
--- /dev/null
+++ b/src/declarative/3rdparty/qlistmodelinterface.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLISTMODELINTERFACE_H
+#define QLISTMODELINTERFACE_H
+
+#include <QtCore/QHash>
+#include <QtCore/QVariant>
+#include <QtDeclarative/qfxglobal.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QListModelInterface : public QObject
+{
+ Q_OBJECT
+ public:
+ QListModelInterface(QObject *parent = 0) : QObject(parent) {}
+ virtual ~QListModelInterface() {}
+
+ virtual int count() const = 0;
+ virtual QHash<int,QVariant> data(int index, const QList<int>& roles = QList<int>()) const = 0;
+ virtual bool setData(int index, const QHash<int,QVariant>& values)
+ { Q_UNUSED(index); Q_UNUSED(values); return false; }
+
+ virtual QList<int> roles() const = 0;
+ virtual QString toString(int role) const = 0;
+
+ Q_SIGNALS:
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count, const QList<int> &roles);
+
+ protected:
+ QListModelInterface(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent) {}
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif //QTREEMODELINTERFACE_H
diff --git a/src/declarative/canvas/canvas.pri b/src/declarative/canvas/canvas.pri
new file mode 100644
index 0000000..9bdd3fa
--- /dev/null
+++ b/src/declarative/canvas/canvas.pri
@@ -0,0 +1,19 @@
+SOURCES += \
+ canvas/qsimplecanvas.cpp \
+ canvas/qsimplecanvasitem.cpp \
+ canvas/qsimplecanvasfilter.cpp \
+ canvas/qsimplecanvasdebugplugin.cpp
+
+HEADERS += \
+ canvas/qsimplecanvas.h \
+ canvas/qsimplecanvasitem.h \
+ canvas/qsimplecanvasfilter.h \
+ canvas/qsimplecanvas_p.h \
+ canvas/qsimplecanvasitem_p.h \
+ canvas/qsimplecanvasfilter_p.h \
+ canvas/qsimplecanvasdebugplugin_p.h
+
+contains(QT_CONFIG, opengles2): SOURCES += canvas/qsimplecanvas_opengl.cpp
+else:contains(QT_CONFIG, opengles1): SOURCES += canvas/qsimplecanvas_opengl1.cpp
+else:SOURCES += canvas/qsimplecanvas_software.cpp
+SOURCES += canvas/qsimplecanvas_graphicsview.cpp
diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp
new file mode 100644
index 0000000..e582226
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas.cpp
@@ -0,0 +1,1029 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidget.h"
+#include "qmutex.h"
+#include "qdebug.h"
+#include "qcoreapplication.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas_p.h"
+#include "qtimer.h"
+#include "qdatetime.h"
+#include "qgraphicssceneevent.h"
+#if defined(QFX_RENDER_OPENGL)
+#include <glheaders.h>
+#endif
+#include "qboxlayout.h"
+#include "qsimplecanvasdebugplugin_p.h"
+#include "qsimplecanvas.h"
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(fullUpdate, GFX_CANVAS_FULL_UPDATE);
+DEFINE_BOOL_CONFIG_OPTION(continuousUpdate, GFX_CANVAS_CONTINUOUS_UPDATE);
+DEFINE_BOOL_CONFIG_OPTION(useSimpleCanvas, QFX_USE_SIMPLECANVAS);
+
+template<class T, int s = 60>
+class CircularList
+{
+public:
+ CircularList()
+ : _first(0), _size(0) {}
+
+ void append(const T &t)
+ {
+ int entry = (_first + _size) % s;
+ _array[entry] = t;
+ if (_size == s)
+ _first = (_first + 1) % s;
+ else
+ _size++;
+ }
+
+ int size() const
+ {
+ return _size;
+ }
+
+ T &operator[](int idx)
+ {
+ Q_ASSERT(idx < _size);
+ int entry = (_first + idx) % s;
+ return _array[entry];
+ }
+
+ void clear()
+ {
+ _first = 0;
+ _size = 0;
+ }
+private:
+ int _first;
+ int _size;
+ T _array[s];
+};
+
+
+class QSimpleCanvasRootLayer : public QSimpleCanvasLayer
+{
+public:
+ QSimpleCanvasRootLayer(QSimpleCanvas *);
+ virtual void addDirty(QSimpleCanvasItem *);
+ virtual void remDirty(QSimpleCanvasItem *);
+
+private:
+ friend class QSimpleCanvasItem;
+ QSimpleCanvas *_canvas;
+};
+
+void QSimpleCanvasRootLayer::addDirty(QSimpleCanvasItem *i)
+{
+ _canvas->addDirty(i);
+}
+
+void QSimpleCanvasRootLayer::remDirty(QSimpleCanvasItem *i)
+{
+ _canvas->remDirty(i);
+}
+
+void QSimpleCanvasPrivate::clearFocusPanel(QSimpleCanvasItem *panel)
+{
+ if (q->activeFocusPanel() == panel) {
+ focusPanels.pop();
+
+ switchToFocusPanel(q->activeFocusPanel(), panel, Qt::OtherFocusReason);
+ panel->activePanelOutEvent();
+ } else {
+ for (int ii = 0; ii < focusPanels.count(); ++ii)
+ if (focusPanels.at(ii) == panel) {
+ focusPanels.remove(ii);
+ break;
+ }
+ }
+}
+
+void QSimpleCanvasPrivate::switchToFocusPanel(QSimpleCanvasItem *panel, QSimpleCanvasItem *wasPanel, Qt::FocusReason focusReason)
+{
+ if (panel)
+ panel->activePanelInEvent();
+
+ QSimpleCanvasItem *wasFocusRoot = focusPanelData.value(wasPanel);
+ if (wasFocusRoot)
+ clearActiveFocusItem(wasFocusRoot, focusReason);
+
+ QSimpleCanvasItem *newFocusRoot = focusPanelData.value(panel);
+ if (newFocusRoot)
+ setFocusItem(newFocusRoot, focusReason);
+}
+
+void QSimpleCanvasPrivate::setActiveFocusPanel(QSimpleCanvasItem *panel, Qt::FocusReason focusReason)
+{
+ if (q->activeFocusPanel() == panel)
+ return;
+
+ if (panel) {
+ for (int ii = 0; ii < focusPanels.count(); ++ii)
+ if (focusPanels.at(ii) == panel) {
+ focusPanels.remove(ii);
+ break;
+ }
+ }
+ QSimpleCanvasItem *old = q->activeFocusPanel();
+ if (panel)
+ focusPanels << panel;
+ switchToFocusPanel(panel, old, focusReason);
+ if (old)
+ old->activePanelOutEvent();
+}
+
+void QSimpleCanvasPrivate::clearActiveFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason)
+{
+ if (!item || !item->d_func())
+ return;
+
+ if (!item->d_func()->hasActiveFocus)
+ return;
+
+ item->d_func()->hasActiveFocus = false;
+ if (item->options() & QSimpleCanvasItem::IsFocusRealm) {
+ QSimpleCanvasItem *newItem = focusPanelData.value(item);
+ if (newItem) {
+ clearActiveFocusItem(newItem, focusReason);
+ } else {
+ focusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ item->focusOutEvent(&event);
+ }
+ } else {
+ focusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ item->focusOutEvent(&event);
+ }
+
+ if (item->options() & QSimpleCanvasItem::AcceptsInputMethods){
+ if (q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->setAttribute(Qt::WA_InputMethodEnabled,false);
+ }
+ item->activeFocusChanged(true);
+}
+
+void QSimpleCanvasPrivate::setActiveFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason)
+{
+ while(true) {
+ item->d_func()->setActiveFocus(true);
+ item->activeFocusChanged(true);
+ if (item->options() & QSimpleCanvasItem::IsFocusRealm) {
+ QSimpleCanvasItem *newItem = focusPanelData.value(item);
+ if (newItem)
+ item = newItem;
+ else
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if (item->options() & QSimpleCanvasItem::AcceptsInputMethods){
+ if (!q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->setAttribute(Qt::WA_InputMethodEnabled,true);
+ }
+ focusItem = item;
+ QFocusEvent event(QEvent::FocusIn, focusReason);
+ focusItem->focusInEvent(&event);
+}
+
+void QSimpleCanvasPrivate::clearFocusItem(QSimpleCanvasItem *item)
+{
+ // XXX
+#if 0
+ while(item->focusProxy())
+ item = item->focusProxy();
+#endif
+
+ QSimpleCanvasItem *scope = 0;
+ QSimpleCanvasItem *citem = item;
+ while(citem && !scope) {
+ if (citem->options() & QSimpleCanvasItem::IsFocusPanel)
+ scope = citem;
+ else if (citem != item && citem->options() & QSimpleCanvasItem::IsFocusRealm)
+ scope = citem;
+ citem = citem->parent();
+ }
+ Q_ASSERT(scope); // At the very least we'll find the canvas root
+
+ bool isActive = false;
+
+ if (scope->options() & QSimpleCanvasItem::IsFocusPanel)
+ isActive = (scope == q->activeFocusPanel());
+ else if (scope->options() & QSimpleCanvasItem::IsFocusRealm)
+ isActive = scope->hasActiveFocus();
+
+ if (isActive) clearActiveFocusItem(item, Qt::OtherFocusReason);
+ item->d_func()->setFocus(false);
+ item->focusChanged(false);
+
+ focusPanelData.insert(scope, 0);
+
+ if (lastFocusItem == item)
+ lastFocusItem = 0;
+ if (focusItem == item)
+ focusItem = 0;
+
+ if (scope->options() & QSimpleCanvasItem::IsFocusRealm && scope->hasActiveFocus()) {
+ setActiveFocusItem(scope, Qt::OtherFocusReason);
+ } else {
+ QSimpleCanvasItem *item = QSimpleCanvasItem::findNextFocus(scope);
+ if (item)
+ item->setFocus(true);
+ }
+}
+
+void QSimpleCanvasPrivate::setFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason,
+ bool overwrite)
+{
+ Q_ASSERT(item);
+
+ // XXX
+#if 0
+ while(item->focusProxy())
+ item = item->focusProxy();
+#endif
+
+ if (item == focusItem)
+ return;
+
+ QSimpleCanvasItem *scope = 0;
+ QSimpleCanvasItem *citem = item;
+ while(citem && !scope) {
+ if (citem->options() & QSimpleCanvasItem::IsFocusPanel)
+ scope = citem;
+ else if (citem != item && citem->options() & QSimpleCanvasItem::IsFocusRealm)
+ scope = citem;
+ citem = citem->parent();
+ }
+ Q_ASSERT(scope); // At the very least we'll find the canvas root
+
+ if (!overwrite && focusPanelData.contains(scope)) {
+ item->d_func()->setFocus(false);
+ item->focusChanged(false);
+ return;
+ }
+
+ QSimpleCanvasItem *oldFocus = focusPanelData.value(scope);
+ bool isActive = false;
+
+ if (scope->options() & QSimpleCanvasItem::IsFocusPanel)
+ isActive = (scope == q->activeFocusPanel());
+ else if (scope->options() & QSimpleCanvasItem::IsFocusRealm)
+ isActive = scope->hasActiveFocus();
+
+ if (oldFocus) {
+ if (isActive) clearActiveFocusItem(oldFocus, focusReason);
+ oldFocus->d_func()->setFocus(false);
+ oldFocus->focusChanged(false);
+ }
+
+ focusPanelData.insert(scope, item);
+
+ if (isActive)
+ lastFocusItem = item;
+
+ if (item) {
+ item->d_func()->setFocus(true);
+ item->focusChanged(true);
+ if (isActive)
+ setActiveFocusItem(item, focusReason);
+ }
+}
+
+
+bool QSimpleCanvas::eventFilter(QObject *obj, QEvent *event)
+{
+ Q_UNUSED(obj);
+ switch (event->type()) {
+ case QEvent::GraphicsSceneMouseMove: {
+ QGraphicsSceneMouseEvent *me = (QGraphicsSceneMouseEvent*)event;
+ if (!me->buttons())
+ break;
+ }
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease: {
+ //same logic as filter() function
+ for (int ii = 0; ii < d->mouseFilters.count(); ++ii) {
+ if (d->mouseFilters.at(ii)->mouseFilter((QGraphicsSceneMouseEvent*)event))
+ return true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
+void QSimpleCanvasPrivate::installMouseFilter(QSimpleCanvasItem *item)
+{
+ mouseFilters << item;
+}
+
+void QSimpleCanvasPrivate::removeMouseFilter(QSimpleCanvasItem *item)
+{
+ mouseFilters.removeAll(item);
+}
+
+bool QSimpleCanvasPrivate::filter(QMouseEvent *e)
+{
+ if (mouseFilters.isEmpty())
+ return false;
+
+ QGraphicsSceneMouseEvent *me = mouseEventToSceneMouseEvent(e, e->pos());
+ for (int ii = 0; ii < mouseFilters.count(); ++ii) {
+ if (mouseFilters.at(ii)->mouseFilter(me)) {
+ delete me;
+ return true;
+ }
+ }
+ delete me;
+ return false;
+}
+
+QGraphicsSceneMouseEvent *QSimpleCanvasPrivate::mouseEventToSceneMouseEvent(QMouseEvent *e, const QPoint &item)
+{
+ QEvent::Type t;
+ switch(e->type()) {
+ default:
+ case QEvent::MouseButtonPress:
+ t = QEvent::GraphicsSceneMousePress;
+ break;
+ case QEvent::MouseButtonRelease:
+ t = QEvent::GraphicsSceneMouseRelease;
+ break;
+ case QEvent::MouseMove:
+ t = QEvent::GraphicsSceneMouseMove;
+ break;
+ case QEvent::MouseButtonDblClick:
+ t = QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick;
+ break;
+ }
+
+ QGraphicsSceneMouseEvent *me = new QGraphicsSceneMouseEvent(t);
+ me->setButton(e->button());
+ me->setButtons(e->buttons());
+ me->setModifiers(e->modifiers());
+ me->setPos(item);
+ me->setScreenPos(e->pos());
+ me->setScenePos(e->pos());
+ return me;
+}
+
+bool QSimpleCanvasPrivate::deliverMousePress(QSimpleCanvasItem *base, QMouseEvent *e, bool seenChildFilter)
+{
+ if (base->clipType()) {
+ QRectF br = base->boundingRect();
+ QPointF pos = base->mapFromScene(e->pos());
+ if (!br.contains(pos.toPoint()))
+ return false;
+ }
+
+ const QList<QSimpleCanvasItem *> &children = base->d_func()->children;
+
+ if (base->options() & QSimpleCanvasItem::ChildMouseFilter)
+ seenChildFilter = true;
+
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ if (children.at(ii)->visible() != 0.)
+ if (deliverMousePress(children.at(ii), e, seenChildFilter))
+ return true;
+ }
+
+ if (base->acceptedMouseButtons() & e->button() || base->options() & QSimpleCanvasItem::ChildMouseFilter) {
+
+ QRectF br = base->boundingRect();
+ QPoint pos = base->mapFromScene(e->pos()).toPoint();
+
+ if (br.contains(pos)) {
+ QGraphicsSceneMouseEvent *me = mouseEventToSceneMouseEvent(e, pos);
+
+ sendMouseEvent(base, me);
+ bool isAccepted = me->isAccepted();
+ delete me;
+ if (isAccepted) {
+ lastMouseItem = base;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Delivers e to item
+void QSimpleCanvasPrivate::sendMouseEvent(QSimpleCanvasItem *item, QGraphicsSceneMouseEvent *e)
+{
+ QSimpleCanvasItem *p = item->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(e))
+ return;
+ }
+ p = p->parent();
+ }
+ switch(e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ item->mousePressEvent(e);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ item->mouseReleaseEvent(e);
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ item->mouseMoveEvent(e);
+ break;
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ item->mouseDoubleClickEvent(e);
+ break;
+ default:
+ break;
+ }
+}
+
+
+QSimpleCanvasRootLayer::QSimpleCanvasRootLayer(QSimpleCanvas *c)
+: _canvas(c)
+{
+ QSimpleCanvasItem::d_func()->canvas = c;
+ setOptions(IsFocusPanel);
+ update();
+}
+
+
+struct QSimpleCanvasTiming
+{
+ QSimpleCanvasTiming()
+ : time(-1), paintTime(-1), timeBetweenFrames(-1) {}
+ QSimpleCanvasTiming(const QRegion &_r, int _time, int _paintTime,
+ int _timeBetweenFrames)
+ : region(_r), time(_time), paintTime(_paintTime),
+ timeBetweenFrames(_timeBetweenFrames) {}
+ QSimpleCanvasTiming(const QSimpleCanvasTiming &other)
+ : region(other.region), time(other.time), paintTime(other.paintTime),
+ timeBetweenFrames(other.timeBetweenFrames) {}
+ QSimpleCanvasTiming &operator=(const QSimpleCanvasTiming &other) {
+ region = other.region; time = other.time; paintTime = other.paintTime;
+ timeBetweenFrames = other.timeBetweenFrames; return *this;
+ }
+ QRegion region;
+ int time;
+ int paintTime;
+ int timeBetweenFrames;
+};
+
+// XXX
+static CircularList<QSimpleCanvasTiming> gfxCanvasTiming;
+
+void QSimpleCanvasGraphicsView::paintEvent(QPaintEvent *pe)
+{
+ QRegion r = pe->region();
+ int tbf = canvas->frameTimer.restart();
+
+ canvas->lrpTimer.start();
+ QGraphicsView::paintEvent(pe);
+ canvas->lrpTime = canvas->lrpTimer.elapsed();
+
+ int frametimer = canvas->frameTimer.elapsed();
+ gfxCanvasTiming.append(QSimpleCanvasTiming(r, frametimer, canvas->lrpTime, tbf));
+ canvas->lrpTime = 0;
+ if (canvas->debugPlugin)
+ canvas->debugPlugin->addTiming(canvas->lrpTime, frametimer, tbf);
+}
+
+void QSimpleCanvasGraphicsView::focusInEvent(QFocusEvent *)
+{
+}
+
+/*!
+ \internal
+ \class QSimpleCanvas
+ \brief The QSimpleCanvas class implements the canvas used by Qt Declarative
+ */
+
+QSimpleCanvas::QSimpleCanvas(CanvasMode mode, QWidget *parent)
+: QWidget(parent), d(new QSimpleCanvasPrivate(this))
+{
+ d->init(mode);
+}
+
+QSimpleCanvas::QSimpleCanvas(QWidget *parent)
+: QWidget(parent), d(new QSimpleCanvasPrivate(this))
+{
+ d->init(useSimpleCanvas()?SimpleCanvas:GraphicsView);
+}
+
+void QSimpleCanvasPrivate::init(QSimpleCanvas::CanvasMode mode)
+{
+ this->mode = mode;
+
+ if (mode == QSimpleCanvas::SimpleCanvas)
+ qWarning("QSimpleCanvas: Using simple canvas");
+ else
+ qWarning("QSimpleCanvas: Using GraphicsView canvas");
+
+ if (fullUpdate())
+ qWarning("QSimpleCanvas: Full update enabled");
+ if (continuousUpdate())
+ qWarning("QSimpleCanvas: Continuous update enabled");
+
+ if (QmlDebugServerPlugin::isDebuggingEnabled()) {
+ debugPlugin = new QSimpleCanvasDebugPlugin(q);
+ new QSimpleCanvasSceneDebugPlugin(q);
+ }
+
+ root = new QSimpleCanvasRootLayer(q);
+ root->setActiveFocusPanel(true);
+ q->setFocusPolicy(Qt::StrongFocus);
+
+ if (mode == QSimpleCanvas::GraphicsView) {
+ view = new QSimpleCanvasGraphicsView(this);
+ QHBoxLayout *layout = new QHBoxLayout(q);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ q->setLayout(layout);
+ layout->addWidget(view);
+ view->setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view->setFrameStyle(0);
+ static_cast<QSimpleCanvasItemPrivate*>(root->d_ptr)->convertToGraphicsItem();
+ view->scene()->addItem(static_cast<QSimpleCanvasItemPrivate*>(root->d_ptr)->graphicsItem);
+
+ // These seem to give the best performance
+ view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ view->scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
+ view->viewport()->setFocusPolicy(Qt::NoFocus);
+ }
+
+#if defined(QFX_RENDER_OPENGL) && defined(Q_WS_X11)
+ QTimer *t = new QTimer(q);
+ t->setInterval(200);
+ QObject::connect(t, SIGNAL(timeout()), &egl, SLOT(updateGL()));
+ t->start();
+#endif
+}
+
+QSimpleCanvas::~QSimpleCanvas()
+{
+ delete d->root;
+ delete d;
+}
+
+void QSimpleCanvasPrivate::paint(QPainter &p)
+{
+#if defined(QFX_RENDER_QPAINTER)
+ if (!isSetup) {
+ ++paintVersion;
+ root->d_func()->setupPainting(0, q->rect());
+ }
+
+ lrpTimer.start();
+
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QSimpleCanvas::CanvasMode QSimpleCanvas::canvasMode() const
+{
+ return d->mode;
+}
+
+QSimpleCanvasItem *QSimpleCanvas::root()
+{
+ return d->root;
+}
+
+void QSimpleCanvas::keyPressEvent(QKeyEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->keyPressEvent(event);
+ QWidget::keyPressEvent(event);
+}
+
+void QSimpleCanvas::keyReleaseEvent(QKeyEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->keyReleaseEvent(event);
+ QWidget::keyReleaseEvent(event);
+}
+
+void QSimpleCanvas::inputMethodEvent(QInputMethodEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->inputMethodEvent(event);
+ else
+ QWidget::inputMethodEvent(event);
+}
+
+QVariant QSimpleCanvas::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ if (d->focusItem)
+ return d->focusItem->inputMethodQuery(query);
+ return QWidget::inputMethodQuery(query);
+}
+
+void QSimpleCanvas::mousePressEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() &&
+ (d->filter(e) || d->deliverMousePress(d->root, e))) {
+ e->accept();
+ } else {
+ QWidget::mousePressEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() &&
+ (d->filter(e) || d->deliverMousePress(d->root, e))) {
+ e->accept();
+ } else {
+ QWidget::mouseDoubleClickEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseMoveEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() && d->filter(e)) {
+ e->accept();
+ } else if (d->isSimpleCanvas() && d->lastMouseItem) {
+ QPoint p = d->lastMouseItem->mapFromScene(e->pos()).toPoint();
+ QGraphicsSceneMouseEvent *me = d->mouseEventToSceneMouseEvent(e, p);
+ d->sendMouseEvent(d->lastMouseItem, me);
+ e->setAccepted(me->isAccepted());
+ delete me;
+ } else {
+ QWidget::mouseMoveEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() && d->filter(e)) {
+ e->accept();
+ } else if (d->isSimpleCanvas() && d->lastMouseItem) {
+ QPoint p = d->lastMouseItem->mapFromScene(e->pos()).toPoint();
+ QGraphicsSceneMouseEvent *me = d->mouseEventToSceneMouseEvent(e, p);
+ d->sendMouseEvent(d->lastMouseItem, me);
+ d->lastMouseItem->mouseUngrabEvent();
+ e->setAccepted(me->isAccepted());
+ delete me;
+ d->lastMouseItem = 0;
+ } else {
+ QWidget::mouseReleaseEvent(e);
+ }
+}
+
+void QSimpleCanvas::focusInEvent(QFocusEvent *event)
+{
+ // XXX
+#if 0
+ if (d->lastFocusItem && event->reason() == Qt::ActiveWindowFocusReason) {
+ d->setFocusItem(d->lastFocusItem, event->reason());
+ } else {
+ QSimpleCanvasItem *panel = activeFocusPanel();
+ QSimpleCanvasItem *focusItem = 0;
+ if (panel->isFocusable())
+ focusItem = panel;
+ else
+ focusItem = QSimpleCanvasItem::findNextFocus(panel);
+
+ if (focusItem)
+ d->setFocusItem(focusItem, event->reason());
+ else
+ QWidget::focusNextPrevChild(true);
+ }
+#endif
+ QWidget::focusInEvent(event);
+}
+
+void QSimpleCanvas::focusOutEvent(QFocusEvent *event)
+{
+ // XXX
+#if 0
+ if (event->reason() == Qt::ActiveWindowFocusReason) {
+ d->lastFocusItem = activeFocusPanel();
+ d->setActiveFocusPanel(0, Qt::ActiveWindowFocusReason);
+ }
+#endif
+ QWidget::focusOutEvent(event);
+}
+
+bool QSimpleCanvas::focusNextPrevChild(bool)
+{
+ // XXX
+#if 0
+ if (d->focusItem) {
+ QSimpleCanvasItem *item = next ? QSimpleCanvasItem::findNextFocus(d->focusItem) : QSimpleCanvasItem::findPrevFocus(d->focusItem);
+ if (item) {
+ d->setFocusItem(item,
+ next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+ }
+ }
+
+ QSimpleCanvasItem *panel = activeFocusPanel();
+ QSimpleCanvasItem *item = 0;
+ if (panel->isFocusable())
+ item = panel;
+ else
+ item = next ? QSimpleCanvasItem::findNextFocus(panel) : QSimpleCanvasItem::findPrevFocus(panel);
+ if (item && item != d->focusItem) {
+ d->setFocusItem(item,
+ next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+ }
+
+ if (d->focusItem)
+ d->setActiveFocusPanel(0, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+
+#endif
+ return false;
+}
+
+
+void QSimpleCanvas::showEvent(QShowEvent *e)
+{
+#if defined(QFX_RENDER_OPENGL)
+ d->egl.resize(width(), height());
+#endif
+ if (d->isGraphicsView())
+ d->view->setSceneRect(rect());
+
+ QWidget::showEvent(e);
+}
+
+void QSimpleCanvas::resizeEvent(QResizeEvent *e)
+{
+#if defined(QFX_RENDER_OPENGL)
+ d->egl.resize(width(), height());
+#endif
+ if (d->isGraphicsView())
+ d->view->setSceneRect(rect());
+ QWidget::resizeEvent(e);
+}
+
+
+void QSimpleCanvas::remDirty(QSimpleCanvasItem *c)
+{
+ d->dirtyItems.removeAll(c);
+}
+
+void QSimpleCanvas::queueUpdate()
+{
+ if (!d->timer) {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ d->timer = 1;
+ }
+}
+
+void QSimpleCanvas::addDirty(QSimpleCanvasItem *c)
+{
+ queueUpdate();
+ if (d->isSimpleCanvas()) {
+ d->oldDirty |= c->d_func()->data()->lastPaintRect;
+#if defined(QFX_RENDER_OPENGL)
+ // Check for filters
+ QSimpleCanvasItem *fi = c->parent();
+ while(fi) {
+ if (fi->d_func()->data()->dirty) {
+ break;
+ } else if (fi->filter()) {
+ fi->update();
+ break;
+ }
+ fi = fi->parent();
+ }
+#endif
+ d->dirtyItems.append(c);
+ }
+}
+
+QRect QSimpleCanvasPrivate::dirtyItemClip() const
+{
+ QRect rv;
+ if (isSimpleCanvas()) {
+#if defined(QFX_RENDER_OPENGL)
+ QRectF r;
+ for (int ii = 0; ii < dirtyItems.count(); ++ii)
+ r |= dirtyItems.at(ii)->d_func()->data()->lastPaintRect;
+ rv = egl.map(r);
+#else
+ for (int ii = 0; ii < dirtyItems.count(); ++ii)
+ rv |= dirtyItems.at(ii)->d_func()->data()->lastPaintRect;
+#endif
+ }
+ return rv;
+}
+
+QRegion QSimpleCanvasPrivate::resetDirty()
+{
+ if (isSimpleCanvas()) {
+#if defined(QFX_RENDER_OPENGL)
+ QRect r = egl.map(oldDirty) | dirtyItemClip();
+#else
+ QRect r = oldDirty | dirtyItemClip();
+#endif
+ if (!r.isEmpty())
+ r.adjust(-1,-1,2,2); //make sure we get everything (since we rounded from floats to ints)
+ for (int ii = 0; ii < dirtyItems.count(); ++ii)
+ static_cast<QSimpleCanvasItemPrivate*>(dirtyItems.at(ii)->d_ptr)->data()->dirty = false;
+ dirtyItems.clear();
+ oldDirty = QRect();
+
+ if (fullUpdate())
+ return QRegion();
+ else
+ return QRegion(r);
+ } else {
+ return QRegion();
+ }
+}
+
+QSimpleCanvasItem *QSimpleCanvas::focusItem() const
+{
+ return d->focusItem;
+}
+
+QSimpleCanvasItem *QSimpleCanvas::activeFocusPanel() const
+{
+ if (d->focusPanels.isEmpty())
+ return 0;
+ else
+ return d->focusPanels.top();
+}
+
+QSimpleCanvasItem *QSimpleCanvas::focusItem(QSimpleCanvasItem *item) const
+{
+ while (item && d->focusPanelData.contains(item))
+ item = d->focusPanelData.value(item);
+ return item;
+}
+
+bool QSimpleCanvas::event(QEvent *e)
+{
+ if (e->type() == QEvent::User && d->isSimpleCanvas()) {
+ d->timer = 0;
+ d->isSetup = true;
+#if defined(QFX_RENDER_OPENGL1)
+ unsigned int zero = 0;
+ d->root->d_func()->setupPainting(0, rect(), &zero);
+#else
+ ++d->paintVersion;
+ d->root->d_func()->setupPainting(0, rect());
+#endif
+
+ QRegion r = d->resetDirty();
+
+ int tbf = d->frameTimer.restart();
+
+#if defined(QFX_RENDER_QPAINTER)
+ if (r.isEmpty() || fullUpdate())
+ repaint();
+ else
+ repaint(r);
+ emit framePainted();
+#else
+ QRect br = r.boundingRect();
+ QRect nr(br.x(), height() - br.y() - br.height(), br.width(), br.height());
+
+ if (r.isEmpty() || fullUpdate())
+ d->egl.updateGL();
+ else
+ d->egl.updateGL(nr);
+ emit framePainted();
+#endif
+ d->isSetup = false;
+
+ int frametimer = d->frameTimer.elapsed();
+ gfxCanvasTiming.append(QSimpleCanvasTiming(r, frametimer, d->lrpTime, tbf));
+ if (d->debugPlugin)
+ d->debugPlugin->addTiming(d->lrpTime, frametimer, tbf);
+ d->lrpTime = 0;
+ if (continuousUpdate())
+ queueUpdate();
+
+ return true;
+ }
+
+ if (e->type() == QEvent::ShortcutOverride) {
+ if (QSimpleCanvasItem *focus = focusItem())
+ return focus->event(e);
+ }
+
+ return QWidget::event(e);
+}
+
+void QSimpleCanvas::paintEvent(QPaintEvent *)
+{
+#if defined(QFX_RENDER_QPAINTER)
+ if (d->mode == SimpleCanvas) {
+ QPainter p(this);
+ d->paint(p);
+ }
+#endif
+}
+
+void QSimpleCanvas::dumpTiming()
+{
+ for (int ii = 0; ii < gfxCanvasTiming.size(); ++ii) {
+ const QSimpleCanvasTiming &t = gfxCanvasTiming[ii];
+
+ qreal repaintFps = 1000. / qreal(t.time);
+ qreal paintFps = 1000. / qreal(t.paintTime);
+ qreal tbfFps = 1000. / qreal(t.timeBetweenFrames);
+
+ qWarning() << "repaint():" << t.time << "ms," << repaintFps << "fps. paint():" << t.paintTime << "ms," << paintFps << "fps. timeSinceLastFrame:" << t.timeBetweenFrames << "ms," << tbfFps << "fps.";
+ qWarning() << t.region;
+ }
+ gfxCanvasTiming.clear();
+}
+
+void QSimpleCanvas::dumpItems()
+{
+ int items = d->root->d_func()->dump(0);
+ qWarning() << "Total:" << items;
+}
+
+void QSimpleCanvas::checkState()
+{
+ if (d->isSimpleCanvas()) {
+ QSimpleCanvasItemPrivate::FocusStateCheckRDatas r;
+ if (d->root->d_func()->checkFocusState(0, &r))
+ qWarning() << "State OK";
+ }
+}
+
+/*!
+ Returns canvas as an image. Not a fast operation.
+*/
+QImage QSimpleCanvas::asImage() const
+{
+ if (d->isSimpleCanvas()) {
+#if defined(QFX_RENDER_QPAINTER)
+ QImage img(width(),height(),QImage::Format_RGB32);
+ QPainter p(&img);
+ const_cast<QSimpleCanvas*>(this)->d->paint(p);
+ return img;
+#elif defined(QFX_RENDER_OPENGL)
+ return d->egl.grabFrameBuffer();
+#endif
+ } else {
+ QImage img(width(),height(),QImage::Format_RGB32);
+ QPainter p(&img);
+ d->view->render(&p);
+ return img;
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas.h b/src/declarative/canvas/qsimplecanvas.h
new file mode 100644
index 0000000..1cbd3c7
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVAS_H
+#define QSIMPLECANVAS_H
+
+#include <QtDeclarative/qfxglobal.h>
+
+#ifdef QFX_RENDER_OPENGL
+#include <QtGui/qmatrix4x4.h>
+#endif
+
+#include <QtGui/QTransform>
+#include <QtGui/QPainter>
+#include <QtCore/QDebug>
+#include <QtGui/QWidget>
+#include <QtGui/QImage>
+#include <QtGui/QKeyEvent>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+namespace QSimpleCanvasConfig
+{
+ enum ImageType { Opaque, Translucent };
+
+#ifdef QFX_RENDER_OPENGL
+ typedef QMatrix4x4 Matrix;
+ typedef QImage Image;
+
+ inline Matrix transformToMatrix(const QTransform &)
+ {
+ return Matrix(); // XXX
+ }
+ inline QTransform matrixToTransform(const Matrix &)
+ {
+ return QTransform(); // XXX
+ }
+ inline bool needConvert(ImageType, const Image &)
+ { return false; }
+ inline Image convert(ImageType, const Image &i)
+ { return i; }
+ inline Image create(const QSize &s)
+ { return QImage(s, QImage::Format_ARGB32); }
+ inline const Image &toImage(const QImage &i)
+ { return i; }
+
+#elif defined(QFX_RENDER_QPAINTER)
+ typedef QTransform Matrix;
+
+ inline Matrix transformToMatrix(const QTransform &t)
+ { return t; }
+ inline QTransform matrixToTransform(const Matrix &t)
+ { return t; }
+#endif
+}
+
+class QSimpleCanvas;
+class QSimpleCanvasLayer;
+
+class QGraphicsSceneMouseEvent;
+class GLBasicShaders;
+class QSimpleCanvasItem;
+class QSimpleCanvasPrivate;
+class Q_DECLARATIVE_EXPORT QSimpleCanvas : public QWidget
+{
+Q_OBJECT
+public:
+ typedef QSimpleCanvasConfig::Matrix Matrix;
+
+ enum CanvasMode { GraphicsView, SimpleCanvas };
+
+ QSimpleCanvas(QWidget *parent = 0);
+ QSimpleCanvas(CanvasMode, QWidget *parent = 0);
+ virtual ~QSimpleCanvas();
+
+ CanvasMode canvasMode() const;
+
+ QSimpleCanvasItem *root();
+
+ // Debugging
+ void dumpTiming();
+ void dumpItems();
+ void checkState();
+
+ QSimpleCanvasItem *focusItem() const;
+ QSimpleCanvasItem *focusItem(QSimpleCanvasItem *item) const;
+
+ QSimpleCanvasItem *activeFocusPanel() const;
+ QImage asImage() const;
+
+Q_SIGNALS:
+ void framePainted();
+
+protected:
+ virtual bool event(QEvent *);
+ virtual void paintEvent(QPaintEvent *);
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void focusInEvent(QFocusEvent *event);
+ virtual void focusOutEvent(QFocusEvent *event);
+ virtual bool focusNextPrevChild(bool next);
+ virtual bool eventFilter(QObject *obj, QEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *event);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+ virtual void showEvent(QShowEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+private:
+
+ friend class QSimpleCanvasRootLayer;
+ friend class QSimpleCanvasPrivate;
+ friend class QSimpleCanvasItem;
+ friend class QSimpleCanvasItemPrivate;
+ friend class QSimpleCanvasFilter;
+ friend class QSimpleGraphicsItem;
+
+ void queueUpdate();
+ QSimpleCanvasPrivate *d;
+ void addDirty(QSimpleCanvasItem *);
+ void remDirty(QSimpleCanvasItem *);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/canvas/qsimplecanvas_graphicsview.cpp b/src/declarative/canvas/qsimplecanvas_graphicsview.cpp
new file mode 100644
index 0000000..dd4012b
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_graphicsview.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+#include <QGraphicsItem>
+#include <QGraphicsSceneMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+static QHash<QGraphicsScene*,QSimpleCanvas*> sceneMap;
+
+QSimpleCanvasGraphicsView::QSimpleCanvasGraphicsView(QSimpleCanvasPrivate *parent)
+: QGraphicsView(parent->q), canvas(parent)
+{
+ setScene(&_scene);
+ sceneMap[&_scene] = parent->q;
+ setFrameShape(QFrame::NoFrame);
+ viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
+}
+
+QSimpleCanvasGraphicsView::~QSimpleCanvasGraphicsView()
+{
+ sceneMap.remove(&_scene);
+}
+
+QSimpleGraphicsItem::QSimpleGraphicsItem(QSimpleCanvasItem *canvasItem)
+: /*scene(0),*/ owner(canvasItem)
+{
+ setAcceptedMouseButtons(Qt::NoButton);
+}
+
+QSimpleGraphicsItem::~QSimpleGraphicsItem()
+{
+ owner->d_func()->graphicsItem = 0;
+}
+
+void QSimpleGraphicsItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *, QWidget *)
+{
+ owner->paintContents(*painter);
+}
+
+QRectF QSimpleGraphicsItem::boundingRect() const
+{
+ return owner->boundingRect();
+}
+
+void QSimpleGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mousePressEvent(event);
+}
+
+void QSimpleGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mouseReleaseEvent(event);
+ ungrabMouse();
+}
+
+void QSimpleGraphicsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mouseDoubleClickEvent(event);
+}
+
+void QSimpleGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mouseMoveEvent(event);
+}
+
+bool QSimpleGraphicsItem::sceneEvent(QEvent *event)
+{
+ bool rv = QGraphicsItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse)
+ owner->mouseUngrabEvent();
+ return rv;
+}
+
+QVariant QSimpleGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ if (change == ItemSceneHasChanged) {
+ QSimpleCanvasItemPrivate *owner_d = static_cast<QSimpleCanvasItemPrivate*>(owner->d_ptr);
+ QSimpleCanvas *oldCanvas = owner_d->canvas;
+ owner_d->canvas = sceneMap[scene()];
+ if (owner_d->canvas){
+ if (owner->hasFocus())
+ owner->canvas()->d->setFocusItem(owner, Qt::OtherFocusReason);
+ if (owner->options() & QSimpleCanvasItem::IsFocusPanel) {
+ if (owner_d->wantsActiveFocusPanelPendingCanvas) {
+ owner_d->hasBeenActiveFocusPanel = true;
+ owner->canvas()->d->setActiveFocusPanel(owner);
+ owner_d->wantsActiveFocusPanelPendingCanvas = false;
+ }
+ }
+ }
+ if (owner->options() & QSimpleCanvasItem::MouseFilter)
+ owner_d->gvRemoveMouseFilter();
+
+ if (oldCanvas != owner_d->canvas)
+ owner->canvasChanged();
+
+ if (owner->options() & QSimpleCanvasItem::MouseFilter)
+ owner_d->gvAddMouseFilter();
+ }
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void QSimpleGraphicsItem::keyPressEvent(QKeyEvent *event)
+{
+ owner->keyPressEvent(event);
+ QGraphicsItem::keyPressEvent(event);
+}
+
+void QSimpleGraphicsItem::keyReleaseEvent(QKeyEvent *event)
+{
+ owner->keyReleaseEvent(event);
+ QGraphicsItem::keyReleaseEvent(event);
+}
+
+void QSimpleGraphicsItem::focusInEvent(QFocusEvent *)
+{
+ if (!owner->hasFocus())
+ owner->setFocus(true);
+}
+
+void QSimpleCanvasItemPrivate::gvRemoveMouseFilter()
+{
+ QGraphicsScene *scene = graphicsItem->scene();
+ if (!scene) return;
+
+ scene->removeEventFilter(q_ptr);
+}
+
+void QSimpleCanvasItemPrivate::gvAddMouseFilter()
+{
+ QGraphicsScene *scene = graphicsItem->scene();
+ if (!scene) return;
+
+ scene->installEventFilter(q_ptr);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp
new file mode 100644
index 0000000..ec809ff
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp
@@ -0,0 +1,474 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvasfilter_p.h"
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <gltexture.h>
+#include <math.h>
+
+
+QT_BEGIN_NAMESPACE
+void CanvasEGLWidget::paintGL()
+{
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ _canvas->paintGL();
+}
+
+void CanvasEGLWidget::updateGL()
+{
+ _clip = QRect();
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::updateGL(const QRect &r)
+{
+ if (r.isEmpty())
+ return;
+
+ _clip = r;
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::resizeGL(int w, int h)
+{
+ glViewport(0, 0, w, h);
+}
+
+QRect CanvasEGLWidget::map(const QRectF &f) const
+{
+ return invDefaultTransform.mapRect(f).toAlignedRect();
+}
+
+void CanvasEGLWidget::resizeEvent(QResizeEvent *e)
+{
+ defaultTransform.setIdentity();
+ defaultTransform.flipCoordinates();
+ defaultTransform.translate(-1, -1, 0);
+ defaultTransform.scale(2. / width(), 2. / height(), 1. / (1024. * 1024.));
+ invDefaultTransform = defaultTransform.inverted();
+ _canvas->root->d_func()->data()->transformActive = defaultTransform;
+ _canvas->root->d_func()->data()->transformValid = true;
+
+ QGLWidget::resizeEvent(e);
+}
+
+void CanvasEGLWidget::initializeGL()
+{
+ glEnable(GL_BLEND);
+ glEnable(GL_STENCIL_TEST);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glStencilFunc(GL_EQUAL, 0, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+}
+
+void QSimpleCanvasPrivate::paintGL()
+{
+ lrpTimer.start();
+
+ QSimpleCanvasItemPrivate::GLPaintParameters p;
+ p.sceneRect = QRect(0, 0, q->width(), q->height());
+ p.clipRect = p.sceneRect;
+ p.stencilValue = 0;
+ p.opacity = 1;
+ p.forceParamRefresh = false;
+ if (!isSetup)
+ root->d_func()->setupPainting(0, QRect());
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+}
+
+QGLFramebufferObject *QSimpleCanvasPrivate::acquire(int w, int h)
+{
+ if (w <= 0 || h <= 0)
+ return 0;
+
+ int size = qMax(w, h);
+ for (int ii = 0; ii < frameBuffers.count(); ++ii) {
+ if (frameBuffers.at(ii)->width() >= size) {
+ QGLFramebufferObject *rv = frameBuffers.at(ii);
+ frameBuffers.removeAt(ii);
+ return rv;
+ }
+ }
+
+ // Find power of two
+ size--;
+ size |= size >> 1;
+ size |= size >> 2;
+ size |= size >> 4;
+ size |= size >> 8;
+ size |= size >> 16;
+ size++;
+
+ QGLFramebufferObject *fbo = new QGLFramebufferObject(size, size);
+ return fbo;
+}
+
+void QSimpleCanvasPrivate::release(QGLFramebufferObject *buf)
+{
+ int size = qMax(buf->width(), buf->height());
+ for (int ii = 0; ii < frameBuffers.count(); ++ii) {
+ if (frameBuffers.at(ii)->width() >= size) {
+ frameBuffers.insert(ii, buf);
+ return;
+ }
+ }
+ frameBuffers.append(buf);
+}
+
+GLBasicShaders *QSimpleCanvasItemPrivate::basicShaders() const
+{
+ return canvas->d->basicShaders();
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItemPrivate::localTransform() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QSimpleCanvas::Matrix trans;
+ trans.translate(q->x(), q->y());
+ QPointF to = transformOrigin();
+ trans.translate(to.x(), to.y());
+ trans.scale(q->scale(), q->scale());
+ trans.translate(-to.x(), -to.y());
+ if (data()->transformUser)
+ trans *= *data()->transformUser;
+ return trans;
+}
+
+void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters &params, QSimpleCanvasItem *child)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ GLPaintParameters childParams = params;
+ if (clip)
+ ++childParams.stencilValue;
+
+ if (child->d_func()->data()->activeOpacity != 0) {
+ childParams.boundingRect = child->boundingRect();
+
+ if (child->filter() && child->filter()->enabled()) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = child->d_func()->data()->transformActive;
+ painter.activeOpacity = child->d_func()->data()->activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+ child->filter()->d->doFilterGL(painter, childParams);
+ } else {
+ child->d_func()->paint(childParams);
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(const GLPaintParameters &params,
+ QSimpleCanvasItem *child)
+{
+ if (params.forceParamRefresh) {
+ QSimpleCanvas::Matrix t = child->d_func()->data()->transformActive;
+ qreal o = child->d_func()->data()->activeOpacity;
+ setupChildState(child);
+ simplePaintChild(params, child);
+ child->d_func()->data()->transformActive = t;
+ child->d_func()->data()->transformValid = true;
+ child->d_func()->data()->activeOpacity = o;
+ } else {
+ simplePaintChild(params, child);
+ }
+}
+
+void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child)
+{
+ QSimpleCanvasItemData *const myData = data();
+ QSimpleCanvasItemPrivate *const childPrivate = child->d_func();
+ QSimpleCanvasItemData *const childData = childPrivate->data();
+
+ childData->activeOpacity = myData->activeOpacity;
+ if (childData->visible != 1)
+ childData->activeOpacity *= childData->visible;
+
+ if (childData->activeOpacity != 0) {
+ // Calculate child's transform
+ const qreal x = childData->x;
+ const qreal y = childData->y;
+ const qreal scale = childPrivate->scale;
+ QSimpleCanvasItem::Flip flip = childData->flip;
+
+ QSimpleCanvas::Matrix &am = childData->transformActive;
+ am = myData->transformActive;
+ if (x != 0. || y != 0.)
+ am.translate(x, y);
+
+ if (scale != 1.) {
+ QPointF to = childPrivate->transformOrigin();
+ bool translate = (to.x() != 0. || to.y() != 0.);
+ if (translate)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if (translate)
+ am.translate(-to.x(), -to.y());
+ }
+
+ if (childData->transformUser)
+ am *= *childData->transformUser;
+
+ if (flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.rotate(180, (flip & QSimpleCanvasItem::VerticalFlip)?1:0, (flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+
+ childData->transformValid = true;
+ }
+}
+
+QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ bool hasContents = options & QSimpleCanvasItem::HasContents;
+
+ QSimpleCanvasItemData *myData = data();
+
+ QRectF rv;
+ if (hasContents) {
+ QRectF filteredBoundRect = q->boundingRect();
+ if (filter)
+ filteredBoundRect = filter->itemBoundingRect(filteredBoundRect);
+ const QMatrix4x4 &active = myData->transformActive;
+
+ rv = active.mapRect(filteredBoundRect);
+ }
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+ setupChildState(child);
+
+ QSimpleCanvasItemData *childData = child->d_func()->data();
+ if (childData->activeOpacity != 0)
+ rv |= child->d_func()->setupPainting(version, bounding);
+ }
+
+ myData->lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvasFilter::Layer layer)
+{
+ if (!layer)
+ return;
+
+ Q_Q(QSimpleCanvasItem);
+
+ GLPaintParameters params = oldParams;
+
+ qreal width = params.boundingRect.width();
+ qreal height = params.boundingRect.height();
+
+ GLfloat vertices[] = { 0, height,
+ width, height,
+ 0, 0,
+ width, 0 };
+
+ // XXX Handle separate cliping modes
+ if (clip) {
+ if (params.stencilValue == 255)
+ qWarning()
+ << "OpenGL: Clip recursion greater than 255 not permitted.";
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+
+ ConstantColorShader *shader = basicShaders()->constantColor();
+ shader->enable();
+ shader->setTransform(data()->transformActive);
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ // XXX Copied from qsimplecanvas_opengl1 scissor based clipping
+ QRectF r = data()->transformActive.mapRect(params.boundingRect);
+ r.translate(1, 1);
+ float xscale = 0.5 * float(params.sceneRect.width());
+ float yscale = 0.5 * float(params.sceneRect.height());
+ r.moveTo(r.x() * xscale, r.y() * yscale);
+ r.setSize(QSizeF(r.width() * xscale, r.height() * yscale));
+ int sr_x = int(::floorf(r.x()));
+ int sr_y = int(::floorf(r.y()));
+ int sr_width = int(::ceilf(r.right())) - sr_x;
+ int sr_height = int(::ceilf(r.bottom())) - sr_y;
+ QRect sr(sr_x, sr_y, sr_width, sr_height);
+ sr.moveTo(sr.x(), params.sceneRect.height() - sr.y() - sr.height());
+ sr &= params.clipRect;
+ params.clipRect = sr;
+ }
+
+ zOrderChildren();
+
+ int upto = 0;
+ for (upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if (c->z() < 0) {
+ if (layer & QSimpleCanvasFilter::ChildrenUnderItem)
+ paintChild(params, c);
+ } else {
+ break;
+ }
+ }
+
+ if (layer & QSimpleCanvasFilter::Item &&
+ q->options() & QSimpleCanvasItem::HasContents) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = data()->transformActive;
+ painter.activeOpacity = data()->activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+
+ q->paintGLContents(painter);
+ }
+
+ if (layer & QSimpleCanvasFilter::ChildrenAboveItem) {
+ for (; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(params, c);
+ }
+ }
+
+ if (clip) {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
+
+ ConstantColorShader *shader = basicShaders()->constantColor();
+ shader->enable();
+ shader->setTransform(data()->transformActive);
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader()
+{
+ if (activeOpacity == 1.) {
+ item->basicShaders()->singleTexture()->enable();
+ item->basicShaders()->singleTexture()->setTransform(activeTransform);
+ return item->basicShaders()->singleTexture();
+ } else {
+ item->basicShaders()->singleTextureOpacity()->enable();
+ item->basicShaders()->singleTextureOpacity()->setTransform(activeTransform);
+ item->basicShaders()->singleTextureOpacity()->setOpacity(activeOpacity);
+ return item->basicShaders()->singleTextureOpacity();
+ }
+
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color)
+{
+ QColor c = color;
+ item->basicShaders()->constantColor()->enable();
+ if (activeOpacity != 1.) {
+ c.setAlpha(int(c.alpha() * activeOpacity));
+ }
+
+ item->basicShaders()->constantColor()->setColor(c);
+ item->basicShaders()->constantColor()->setTransform(activeTransform);
+
+ return item->basicShaders()->constantColor();
+}
+
+void QSimpleCanvasItem::GLPainter::drawPixmap(const QPointF &point,
+ const GLTexture &texture)
+{
+ drawPixmap(QRectF(point, QSizeF(texture.width(), texture.height())), texture);
+}
+
+void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect,
+ const GLTexture &img)
+{
+ QGLShaderProgram *shader = useTextureShader();
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+
+ float widthV = img.width();
+ float heightV = img.height();
+
+ vertices[0] = rect.x(); vertices[1] = rect.y()+heightV;
+ vertices[2] = rect.x()+widthV; vertices[3] = rect.y()+heightV;
+ vertices[4] = rect.x(); vertices[5] = rect.y();
+ vertices[6] = rect.x()+widthV; vertices[7] = rect.y();
+
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = 1; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = 1;
+ texVertices[6] = 1; texVertices[7] = 1;
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, img.texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_opengl1.cpp b/src/declarative/canvas/qsimplecanvas_opengl1.cpp
new file mode 100644
index 0000000..6e50ef8
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_opengl1.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvasfilter_p.h"
+#include <gltexture.h>
+#include <glsave.h>
+#include <math.h>
+
+
+QT_BEGIN_NAMESPACE
+void CanvasEGLWidget::updateGL()
+{
+ _clip = QRect();
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::updateGL(const QRect &r)
+{
+ if (r.isEmpty())
+ return;
+
+ _clip = r;
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::paintGL()
+{
+ if (!_clip.isEmpty()) {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(_clip.x(), _clip.y(), _clip.width(), _clip.height());
+ } else {
+ glDisable(GL_SCISSOR_TEST);
+ }
+
+ glDepthMask(GL_TRUE);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDepthMask(GL_FALSE);
+
+ _canvas->paintGL();
+}
+
+QRect CanvasEGLWidget::map(const QRectF &f)
+{
+ return invDefaultTransform.mapRect(f).toAlignedRect();
+}
+
+void CanvasEGLWidget::resizeGL(int w, int h)
+{
+ glViewport(0, 0, w, h);
+}
+
+void CanvasEGLWidget::resizeEvent(QResizeEvent *e)
+{
+ defaultTransform.identity();
+ defaultTransform.flipCoordinates();
+ defaultTransform.translate(-1, -1, 0);
+ defaultTransform.scale(2. / width(), 2. / height(), -2. / 65536.);
+ invDefaultTransform = defaultTransform.inverted();
+ _canvas->root->d_func()->transformActive = defaultTransform;
+ QGLWidget::resizeEvent(e);
+}
+
+void CanvasEGLWidget::initializeGL()
+{
+ glEnable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDepthFunc(GL_GREATER);
+#ifdef QT_OPENGL_ES
+ glClearDepthf(0);
+#else
+ glClearDepth(0);
+#endif
+}
+
+void QSimpleCanvasPrivate::paintGL()
+{
+ lrpTimer.start();
+
+ QSimpleCanvasItemPrivate::GLPaintParameters p;
+ p.sceneRect = QRect(0, 0, q->width(), q->height());
+ p.clipRect = p.sceneRect;
+ p.opacity = 1;
+ p.forceParamRefresh = false;
+ if (!isSetup) {
+ unsigned int zero = 0;
+ root->d_func()->setupPainting(0, QRect(), &zero);
+ }
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItemPrivate::localTransform() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QSimpleCanvas::Matrix trans;
+ trans.translate(q->x(), q->y());
+ QPointF to = transformOrigin();
+ trans.translate(to.x(), to.y());
+ trans.scale(q->scale().value(), q->scale().value());
+ trans.translate(-to.x(), -to.y());
+ trans *= transformUser;
+ return trans;
+}
+
+void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters &params, QSimpleCanvasItem *child)
+{
+ GLPaintParameters childParams = params;
+
+ if (child->d_func()->activeOpacity != 0) {
+ childParams.boundingRect = child->boundingRect();
+ child->d_func()->paint(childParams);
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(const GLPaintParameters &params,
+ QSimpleCanvasItem *child)
+{
+ if (params.forceParamRefresh) {
+ QSimpleCanvas::Matrix t = child->d_func()->transformActive;
+ qreal o = child->d_func()->activeOpacity;
+ setupChildState(child);
+ simplePaintChild(params, child);
+ child->d_func()->transformActive = t;
+ child->d_func()->activeOpacity = o;
+ } else {
+ simplePaintChild(params, child);
+ }
+}
+
+
+void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child)
+{
+ qreal visible = child->visible().value();
+ child->d_func()->activeOpacity = activeOpacity;
+ if (visible != 1)
+ child->d_func()->activeOpacity *= visible;
+
+ if (child->d_func()->activeOpacity != 0) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale().value();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am = child->d_func()->transformActive;
+ am = transformActive;
+ if (x != 0 || y != 0)
+ am.translate(x, y);
+ if (scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+ if (child->d_func()->transformUserSet)
+ am *= child->d_func()->transformUser;
+ if (flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.rotate(180, (flip & QSimpleCanvasItem::VerticalFlip)?1:0, (flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ }
+}
+
+QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding, unsigned int *zero)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRectF rv = transformActive.mapRect(q->boundingRect());
+
+ unsigned int oldZero = *zero;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+ setupChildState(child);
+
+ if (child->d_func()->activeOpacity != 0)
+ rv |= child->d_func()->setupPainting(version, bounding, zero);
+ }
+
+ if (clip || oldZero != *zero)
+ (*zero)++;
+ transformActive.translate(0, 0, *zero);
+
+ lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paintNoClip(GLPaintParameters &params, QSimpleCanvasFilter::Layer layer)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ zOrderChildren();
+
+ int upto = 0;
+ for (upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if (c->zValue().value() < 0) {
+ if (layer & QSimpleCanvasFilter::ChildrenUnderItem)
+ paintChild(params, c);
+ } else {
+ break;
+ }
+ }
+
+ if (layer & QSimpleCanvasFilter::Item &&
+ q->options() & QSimpleCanvasItem::HasContents) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = transformActive;
+ painter.activeOpacity = activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+
+ q->paintGLContents(painter);
+ }
+
+ if (layer & QSimpleCanvasFilter::ChildrenAboveItem) {
+ for (; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(params, c);
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::paint(GLPaintParameters &params, QSimpleCanvasFilter::Layer layer)
+{
+ if (!layer)
+ return;
+
+ // XXX Handle separate cliping modes
+ if (clip) {
+
+ GLSaveScissor ss;
+ qreal width = params.boundingRect.width();
+ qreal height = params.boundingRect.height();
+ float margin = width + height;
+
+ GLfloat clipvertices[] =
+ {
+ -margin, -margin,
+ margin, -margin,
+ margin, 0,
+
+ -margin, -margin,
+ -margin, 0,
+ margin, 0,
+
+ -margin, 0,
+ -margin, margin,
+ 0, 0,
+
+ 0, 0,
+ 0, margin,
+ -margin, margin,
+
+ 0, height,
+ 0, margin,
+ margin, margin,
+
+ margin, margin,
+ 0, height,
+ margin, height,
+
+ width, 0,
+ margin, 0,
+ margin, height,
+
+ margin, height,
+ width, height,
+ width, 0
+ };
+
+ QRectF r = transformActive.mapRect(params.boundingRect);
+ r.translate(1, 1);
+ float xscale = 0.5 * float(params.sceneRect.width());
+ float yscale = 0.5 * float(params.sceneRect.height());
+ r.moveTo(r.x() * xscale, r.y() * yscale);
+ r.setSize(QSizeF(r.width() * xscale, r.height() * yscale));
+
+ glEnable(GL_SCISSOR_TEST);
+ int sr_x = ::floorf(r.x());
+ int sr_y = ::floorf(r.y());
+ int sr_width = ::ceilf(r.right()) - sr_x;
+ int sr_height = ::ceilf(r.bottom()) - sr_y;
+
+ QRect sr(sr_x, sr_y, sr_width, sr_height);
+ if (ss.wasEnabled())
+ sr &= ss.rect();
+
+ glScissor(sr.x(), sr.y(), sr.width(), sr.height());
+
+ {
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(transformActive.data());
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, clipvertices);
+ glDrawArrays(GL_TRIANGLES, 0, 24);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ }
+
+ GLPaintParameters newParams = params;
+ newParams.clipRect = sr;
+ newParams.clipRect.moveTo(sr.x(), params.sceneRect.height() - sr.y() - sr.height());
+ paintNoClip(newParams, layer);
+ } else {
+ paintNoClip(params, layer);
+ }
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader()
+{
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::useTextureShader() when using OpenGL ES 1.1");
+ return 0;
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color)
+{
+ Q_UNUSED(color);
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::useColorShader() when using OpenGL ES 1.1");
+ return 0;
+}
+
+GLBasicShaders *QSimpleCanvasItemPrivate::basicShaders() const
+{
+ qFatal("Cannot call QSimpleCanvasItem::basicShaders() when using OpenGL ES 1.1");
+ return 0;
+}
+
+QGLFramebufferObject *QSimpleCanvasPrivate::acquire(int, int)
+{
+ return 0;
+}
+
+void QSimpleCanvasPrivate::release(QGLFramebufferObject *)
+{
+}
+
+void QSimpleCanvasItem::GLPainter::drawPixmap(const QPointF &point,
+ const GLTexture &texture)
+{
+ drawPixmap(QRectF(point, QSizeF(texture.width(), texture.height())), texture);
+}
+
+void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect,
+ const GLTexture &img)
+{
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::drawPixmap() when using OpenGL ES 1.1");
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h
new file mode 100644
index 0000000..d9ed4ac
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_p.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVAS_P_H
+#define QSIMPLECANVAS_P_H
+
+#include "qsimplecanvas.h"
+#include <qstack.h>
+#include <qdatetime.h>
+
+#if defined(QFX_RENDER_OPENGL)
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+#endif
+
+#include <QGLWidget>
+QT_BEGIN_NAMESPACE
+
+class CanvasEGLWidget : public QGLWidget
+{
+public:
+ CanvasEGLWidget(QSimpleCanvas *parent, QSimpleCanvasPrivate *canvas)
+ :
+ QGLWidget(parent),
+ _canvas(canvas)
+ {
+ }
+
+ virtual void paintGL();
+ virtual void resizeGL(int,int);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void initializeGL();
+
+ void updateGL();
+ void updateGL(const QRect &);
+
+ QRect map(const QRectF &) const;
+private:
+ QRect _clip;
+ QSimpleCanvasPrivate *_canvas;
+ QSimpleCanvas::Matrix defaultTransform;
+ QSimpleCanvas::Matrix invDefaultTransform;
+};
+#endif
+
+#include <QGraphicsView>
+#include <QGraphicsScene>
+
+struct QSimpleCanvasGraphicsView : public QGraphicsView
+{
+public:
+ QSimpleCanvasGraphicsView(QSimpleCanvasPrivate *parent);
+ ~QSimpleCanvasGraphicsView();
+
+protected:
+ virtual void paintEvent(QPaintEvent *);
+ virtual void focusInEvent(QFocusEvent *);
+
+private:
+ QSimpleCanvasPrivate *canvas;
+ QGraphicsScene _scene;
+};
+
+class QGLFramebufferObject;
+class QSimpleCanvasDebugPlugin;
+class QSimpleCanvasPrivate
+{
+public:
+ QSimpleCanvasPrivate(QSimpleCanvas *canvas)
+ : q(canvas), timer(0), root(0), lrpTime(0), debugPlugin(0), focusItem(0),
+ lastFocusItem(0), lastMouseItem(0),
+ isSetup(false), view(0)
+#if defined(QFX_RENDER_OPENGL)
+ ,egl(q, this), basicShadersInstance(0)
+#endif
+ , paintVersion(1)
+ {
+ }
+
+ QSimpleCanvas *q;
+ QSimpleCanvas::CanvasMode mode;
+ bool isSimpleCanvas() const { return mode == QSimpleCanvas::SimpleCanvas; }
+ bool isGraphicsView() const { return mode == QSimpleCanvas::GraphicsView; }
+
+#if defined(QFX_RENDER_OPENGL)
+ QRectF oldDirty;
+#else
+ QRect oldDirty;
+#endif
+ QRegion resetDirty();
+ void paint(QPainter &p);
+
+
+ int timer;
+
+ QSimpleCanvasLayer *root;
+ QList<QSimpleCanvasItem *> dirtyItems;
+ int lrpTime;
+
+ QTime frameTimer;
+ QTime lrpTimer;
+
+ QSimpleCanvasDebugPlugin *debugPlugin;
+
+ QStack<QSimpleCanvasItem *> focusPanels;
+ QHash<QSimpleCanvasItem *, QSimpleCanvasItem *> focusPanelData;
+ QSimpleCanvasItem *focusItem;
+ QSimpleCanvasItem *lastFocusItem;
+
+ QRect dirtyItemClip() const;
+ void clearFocusPanel(QSimpleCanvasItem *);
+ void setActiveFocusPanel(QSimpleCanvasItem *, Qt::FocusReason focusReason = Qt::OtherFocusReason);
+ void switchToFocusPanel(QSimpleCanvasItem *, QSimpleCanvasItem *, Qt::FocusReason focusReason);
+
+ void setFocusItem(QSimpleCanvasItem *item, Qt::FocusReason focusReason,
+ bool overwrite = true);
+ void clearFocusItem(QSimpleCanvasItem *item);
+
+ void clearActiveFocusItem(QSimpleCanvasItem *, Qt::FocusReason focusReason);
+ void setActiveFocusItem(QSimpleCanvasItem *, Qt::FocusReason focusReason);
+ void installMouseFilter(QSimpleCanvasItem *);
+ void removeMouseFilter(QSimpleCanvasItem *);
+ QList<QSimpleCanvasItem *> mouseFilters;
+ bool filter(QMouseEvent *e);
+ bool deliverMousePress(QSimpleCanvasItem *, QMouseEvent *, bool = false);
+ QGraphicsSceneMouseEvent *mouseEventToSceneMouseEvent(QMouseEvent *, const QPoint &);
+ QSimpleCanvasItem *lastMouseItem;
+ void sendMouseEvent(QSimpleCanvasItem *, QGraphicsSceneMouseEvent *);
+
+ bool isSetup;
+
+ void init(QSimpleCanvas::CanvasMode mode);
+
+ QSimpleCanvasGraphicsView *view;
+
+#if defined(QFX_RENDER_OPENGL)
+ CanvasEGLWidget egl;
+ GLBasicShaders *basicShaders() const
+ {
+#if defined(QFX_RENDER_OPENGL2)
+ if (!basicShadersInstance)
+ basicShadersInstance = new GLBasicShaders;
+ return basicShadersInstance;
+#else
+ return 0;
+#endif
+ }
+ mutable GLBasicShaders *basicShadersInstance;
+
+ QList<QGLFramebufferObject *> frameBuffers;
+ QGLFramebufferObject *acquire(int, int);
+ void release(QGLFramebufferObject *);
+ void paintGL();
+#endif
+ int paintVersion;
+};
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_software.cpp b/src/declarative/canvas/qsimplecanvas_software.cpp
new file mode 100644
index 0000000..dd5e201
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_software.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QRect QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ bool hasContents = options & QSimpleCanvasItem::HasContents;
+
+ QRect rv;
+
+ if (hasContents || q->clip()) {
+ QRectF boundingRectActive = q->boundingRect();
+ rv = data()->transformActive.mapRect(boundingRectActive).toAlignedRect() & bounding;
+ }
+
+ data()->doNotPaint = rv.isEmpty();
+ data()->doNotPaintChildren = data()->doNotPaint && q->clip();
+ QRect myBounding = bounding;
+ if (q->clip())
+ myBounding &= rv;
+
+ if (!data()->doNotPaintChildren) {
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+
+ int childVersion = version;
+ if (!child->d_func()->data()->transformValid)
+ childVersion = canvas->d->paintVersion;
+
+ bool recalcNeeded =
+ (childVersion > child->d_func()->data()->transformVersion);
+
+ if (recalcNeeded) {
+ qreal visible = child->visible();
+ child->d_func()->data()->activeOpacity = data()->activeOpacity;
+ if (visible != 1)
+ child->d_func()->data()->activeOpacity *= visible;
+ }
+
+ if (child->d_func()->data()->activeOpacity != 0) {
+ if (recalcNeeded) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am =
+ child->d_func()->data()->transformActive;
+ am = data()->transformActive;
+ if (x != 0 || y != 0)
+ am.translate(x, y);
+ if (scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+
+ if (child->d_func()->data()->transformUser)
+ am = *child->d_func()->data()->transformUser * am;
+
+ if (flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.scale((flip & QSimpleCanvasItem::HorizontalFlip)?-1:1,
+ (flip & QSimpleCanvasItem::VerticalFlip)?-1:1);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ child->d_func()->data()->transformValid = true;
+ child->d_func()->data()->transformVersion = childVersion;
+ }
+ rv |= child->d_func()->setupPainting(child->d_func()->data()->transformVersion, myBounding);
+ }
+ }
+ }
+
+ data()->lastPaintRect = rv;
+ if (!data()->doNotPaintChildren) {
+ if (!bounding.intersects(rv)) {
+ data()->doNotPaintChildren = true;
+ data()->doNotPaint = true;
+ }
+ }
+
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paint(QPainter &p)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRect oldUcr;
+ if (clip) {
+
+ p.save();
+ QRectF boundingRectActive = q->boundingRect();
+
+ QRect cr;
+ switch(clip) {
+ case QSimpleCanvasItem::ClipToHeight:
+ {
+ qWarning("QSimpleCanvasItem: ClipToHeight not implemented");
+ QRect r = p.clipRegion().boundingRect();
+ cr = QRect(r.x(), 0, r.width(),
+ boundingRectActive.height());
+ }
+ break;
+ case QSimpleCanvasItem::ClipToWidth:
+ {
+ qWarning("QSimpleCanvasItem: ClipToWidth not implemented");
+ QRect r = p.clipRegion().boundingRect();
+ cr = QRect(0, r.y(), boundingRectActive.width(),
+ r.height());
+ }
+ break;
+ case QSimpleCanvasItem::ClipToRect:
+ cr = boundingRectActive.toAlignedRect();
+ break;
+ default:
+ break;
+ }
+
+ p.setWorldTransform(data()->transformActive);
+ if (p.clipRegion().isEmpty()) {
+ p.setClipRect(cr);
+ } else {
+ p.setClipRect(cr, Qt::IntersectClip);
+ }
+
+ if (p.clipRegion().isEmpty()) {
+ p.restore();
+ return;
+ }
+ }
+
+ zOrderChildren();
+
+ int upto = 0;
+ if (!data()->doNotPaintChildren) {
+ for (upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if (c->z() < 0) {
+ paintChild(p, c);
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (!data()->doNotPaint) {
+ p.setWorldTransform(data()->transformActive);
+ q->paintContents(p);
+ }
+
+ if (!data()->doNotPaintChildren) {
+ for (; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(p, c);
+ }
+ }
+
+ if (clip)
+ p.restore();
+
+ if (debuggerStatus && debuggerStatus->selected) {
+ p.setWorldTransform(data()->transformActive);
+ p.fillRect(q->boundingRect(), QColor(255, 0, 0, 80));
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(QPainter &p, QSimpleCanvasItem *c)
+{
+ if (c->d_func()->data()->activeOpacity != 0) {
+
+ qreal op = p.opacity();
+ p.setOpacity(c->d_func()->data()->activeOpacity);
+
+ c->d_func()->paint(p);
+
+ p.setOpacity(op);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasdebugplugin.cpp b/src/declarative/canvas/qsimplecanvasdebugplugin.cpp
new file mode 100644
index 0000000..12088c1
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasdebugplugin.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvasdebugplugin_p.h"
+#include "qdebug.h"
+#include <QtCore/qabstractanimation.h>
+#include <qsimplecanvas.h>
+#include <qsimplecanvasitem.h>
+
+QT_BEGIN_NAMESPACE
+
+class FrameBreakAnimation : public QAbstractAnimation
+{
+public:
+ FrameBreakAnimation(QSimpleCanvasDebugPlugin *s)
+ : QAbstractAnimation(s), server(s)
+ {
+ start();
+ }
+
+ virtual int duration() const { return -1; }
+ virtual void updateCurrentTime(int msecs) {
+ Q_UNUSED(msecs);
+ server->frameBreak();
+ }
+
+private:
+ QSimpleCanvasDebugPlugin *server;
+};
+
+QSimpleCanvasDebugPlugin::QSimpleCanvasDebugPlugin(QObject *parent)
+: QmlDebugServerPlugin(QLatin1String("CanvasFrameRate"), parent), _breaks(0)
+{
+ _time.start();
+ new FrameBreakAnimation(this);
+}
+
+void QSimpleCanvasDebugPlugin::addTiming(quint32 paint,
+ quint32 repaint,
+ quint32 timeBetweenFrames)
+{
+ if (!isEnabled())
+ return;
+
+ bool isFrameBreak = _breaks > 1;
+ _breaks = 0;
+ int e = _time.elapsed();
+ QByteArray data;
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << (int)paint << (int)repaint << (int)timeBetweenFrames << (int)e
+ << (bool)isFrameBreak;
+ sendMessage(data);
+}
+
+void QSimpleCanvasDebugPlugin::frameBreak()
+{
+ _breaks++;
+}
+
+QSimpleCanvasSceneDebugPlugin::QSimpleCanvasSceneDebugPlugin(QSimpleCanvas *parent)
+: QmlDebugServerPlugin(QLatin1String("CanvasScene"), parent), m_canvas(parent)
+{
+}
+
+void QSimpleCanvasSceneDebugPlugin::messageReceived(const QByteArray &)
+{
+ refresh();
+}
+
+void QSimpleCanvasSceneDebugPlugin::refresh()
+{
+ QByteArray data;
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ const QList<QSimpleCanvasItem *> &children = m_canvas->root()->children();
+ ds << children.count();
+ for (int ii = 0; ii < children.count(); ++ii)
+ refresh(ds, children.at(ii));
+
+ sendMessage(data);
+}
+
+void QSimpleCanvasSceneDebugPlugin::refresh(QDataStream &ds,
+ QSimpleCanvasItem *item)
+{
+ ds << QmlDebugServerPlugin::objectToString(item) << item->x() << item->y()
+ << item->z() << item->width() << item->height()
+ << (int)item->transformOrigin() << item->scale() << (int)item->flip()
+#ifdef QFX_RENDER_OPENGL
+ << item->transform().toTransform()
+#elif defined(QFX_RENDER_QPAINTER)
+ << item->transform()
+#endif
+ << item->hasActiveFocus() << (int)item->options();
+
+ QPixmap pix;
+
+ if(item->options() & QSimpleCanvasItem::HasContents &&
+ item->width() > 0 && item->height() > 0) {
+
+ pix = QPixmap(item->width(), item->height());
+ pix.fill(QColor(0,0,0,0));
+ QPainter p(&pix);
+ item->paintContents(p);
+
+ }
+
+ ds << pix;
+
+ const QList<QSimpleCanvasItem *> &children = item->children();
+ ds << children.count();
+
+ for(int ii = 0; ii < children.count(); ++ii)
+ refresh(ds, children.at(ii));
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/canvas/qsimplecanvasdebugplugin_p.h b/src/declarative/canvas/qsimplecanvasdebugplugin_p.h
new file mode 100644
index 0000000..270b78c
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasdebugplugin_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASDEBUGPLUGIN_P_H
+#define QSIMPLECANVASDEBUGPLUGIN_P_H
+
+#include "qobject.h"
+#include "qtcpserver.h"
+#include "qtcpsocket.h"
+#include "qdatetime.h"
+#include <QtDeclarative/qmldebugserver.h>
+
+QT_BEGIN_NAMESPACE
+class QSimpleCanvasDebugPlugin : public QmlDebugServerPlugin
+{
+public:
+ QSimpleCanvasDebugPlugin(QObject *parent = 0);
+
+ void addTiming(quint32, quint32, quint32);
+
+private:
+ friend class FrameBreakAnimation;
+ void frameBreak();
+ int _breaks;
+ QTime _time;
+};
+
+class QSimpleCanvas;
+class QSimpleCanvasItem;
+class QSimpleCanvasSceneDebugPlugin : public QmlDebugServerPlugin
+{
+public:
+ QSimpleCanvasSceneDebugPlugin(QSimpleCanvas *parent = 0);
+
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ void refresh();
+ void refresh(QDataStream &, QSimpleCanvasItem *);
+ QSimpleCanvas *m_canvas;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QSIMPLECANVASDEBUGPLUGIN_P_H
+
diff --git a/src/declarative/canvas/qsimplecanvasfilter.cpp b/src/declarative/canvas/qsimplecanvasfilter.cpp
new file mode 100644
index 0000000..5bc6b35
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvasfilter.h"
+#include "qsimplecanvasfilter_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Filter
+ \brief A Filter is a graphical filter that can be applied to items.
+*/
+
+QSimpleCanvasFilter::QSimpleCanvasFilter(QObject *parent)
+: QObject(parent), d(new QSimpleCanvasFilterPrivate(this))
+{
+}
+
+QSimpleCanvasFilter::~QSimpleCanvasFilter()
+{
+ if (d->item) d->item->setFilter(0);
+ delete d; d = 0;
+}
+
+bool QSimpleCanvasFilter::enabled() const
+{
+ return d->enabled;
+}
+
+/*!
+ \qmlproperty bool Filter::enabled
+ \brief Controls whether the filter is applied.
+*/
+
+void QSimpleCanvasFilter::setEnabled(bool e)
+{
+ if (e == d->enabled)
+ return;
+ d->enabled = e;
+ emit enabledChanged();
+ update();
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::renderToFBO(float scale, const QRectF &src, const QPoint &offset, Layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+
+ QSimpleCanvasItem *item = d->item;
+ QRect br = item->itemBoundingRect();
+ if (br.isEmpty())
+ return 0;
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(int(br.width() * scale), int(br.height() * scale));
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ qreal oldOpacity = item->d_func()->data()->activeOpacity;
+ item->d_func()->data()->activeOpacity = 1;
+
+ fbo->bind();
+
+ glClearColor(0,0,0,0);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, int(br.width() * scale), int(br.height() * scale));
+ glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, int(br.width() * scale), int(br.height() * scale));
+
+ QMatrix4x4 mat;
+ mat.flipCoordinates();
+ mat.translate(-1, -1, 0);
+ mat.scale(2. / (br.width()), 2. / (br.height()), 1. / (1024. * 1024.));
+
+ renderToScreen(mat);
+
+ fbo->release();
+
+ item->d_func()->data()->activeOpacity = oldOpacity;
+ return fbo;
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+ Q_UNUSED(scale);
+ return 0;
+#endif
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::renderToFBO(const QRectF &src, const QPoint &offset, Layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+
+ QSimpleCanvasItem *item = d->item;
+ QRect br = item->itemBoundingRect();
+ if (br.isEmpty())
+ return 0;
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(br.width(), br.height());
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ qreal oldOpacity = item->d_func()->data()->activeOpacity;
+ item->d_func()->data()->activeOpacity = 1;
+
+ fbo->bind();
+
+ glClearColor(0,0,0,0);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, br.width(), br.height());
+ glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, br.width(), br.height());
+
+ QMatrix4x4 mat;
+ mat.flipCoordinates();
+ mat.translate(-1, -1, 0);
+ mat.scale(2. / br.width(), 2. / br.height(), 1. / (1024. * 1024.));
+
+ renderToScreen(mat);
+
+ fbo->release();
+
+ item->d_func()->data()->activeOpacity = oldOpacity;
+ return fbo;
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+ return 0;
+#endif
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::acquireFBO(const QSize &s)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ QSize size;
+ QSimpleCanvasItem *item = d->item;
+ if (size.isNull()) {
+ QRect br = item->itemBoundingRect();
+ size = br.size();
+ } else {
+ size = s;
+ }
+
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(s.width(), s.height());
+
+ return fbo;
+#else
+ Q_UNUSED(s);
+ return 0;
+#endif
+}
+
+void QSimpleCanvasFilter::releaseFBO(QGLFramebufferObject *fbo)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ d->item->d_func()->canvas->d->release(fbo);
+#else
+ Q_UNUSED(fbo);
+#endif
+}
+
+void QSimpleCanvasFilter::renderToScreen(const QRectF &src, Layer layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+ d->item->d_func()->paint(d->params, layer);
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+#endif
+}
+
+void QSimpleCanvasFilter::renderToScreen(const QSimpleCanvas::Matrix &trans, const QRectF &src, Layer layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ QSimpleCanvas::Matrix old = d->item->d_func()->data()->transformActive;
+ d->item->d_func()->data()->transformActive = trans;
+ QSimpleCanvasItemPrivate::GLPaintParameters params = d->params;
+ params.forceParamRefresh = true;
+ d->item->d_func()->paint(params, layer);
+ d->item->d_func()->data()->transformActive = old;
+#else
+ Q_UNUSED(trans);
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+#endif
+}
+
+QSimpleCanvasItem *QSimpleCanvasFilter::item() const
+{
+ return d->item;
+}
+
+void QSimpleCanvasFilter::setItem(QSimpleCanvasItem *i)
+{
+ if (d->item == i)
+ return;
+ if (d->item) {
+ d->item->setFilter(0);
+ d->item = 0;
+ }
+
+ if (i->filter() != this) {
+ i->setFilter(this);
+ } else {
+ d->item = i;
+ }
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+void QSimpleCanvasFilterPrivate::doFilterGL(QSimpleCanvasItem::GLPainter &p, const QSimpleCanvasItemPrivate::GLPaintParameters &prms)
+{
+ params = prms;
+ q->filterGL(p);
+}
+#endif
+
+QRectF QSimpleCanvasFilter::itemBoundingRect(const QRectF &r) const
+{
+ return r;
+}
+
+void QSimpleCanvasFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+ Q_UNUSED(p);
+}
+
+void QSimpleCanvasFilter::filter(QPainter &)
+{
+}
+
+void QSimpleCanvasFilter::update()
+{
+ if (d->item)
+ d->item->update();
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+bool QSimpleCanvasFilterPrivate::isSimpleItem(QSimpleCanvasItem *item, QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout)
+{
+ if (item->options() & QSimpleCanvasItem::SimpleItem && !item->hasChildren()) {
+ *out = item;
+ return true;
+ } else if (!(item->options() & QSimpleCanvasItem::HasContents) &&
+ item->children().count() == 1) {
+ QSimpleCanvasItem *child = item->children().first();
+ if (child->filter() && child->filter()->enabled())
+ return false;
+ bool rv = isSimpleItem(child, out, mout);
+ if (rv)
+ *mout *= child->d_func()->localTransform();
+ return rv;
+ } else {
+ return false;
+ }
+}
+#endif
+
+bool QSimpleCanvasFilter::isSimpleItem(QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ return d->isSimpleItem(item(), out, mout);
+#else
+ Q_UNUSED(out);
+ Q_UNUSED(mout);
+#endif
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasfilter.h b/src/declarative/canvas/qsimplecanvasfilter.h
new file mode 100644
index 0000000..14bb765
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASFILTER_H
+#define QSIMPLECANVASFILTER_H
+
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qsimplecanvasitem.h>
+#include <QtDeclarative/qsimplecanvas.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QSimpleCanvasFilterPrivate;
+class QRectF;
+class QPoint;
+class QGLFramebufferObject;
+class GLShaderProgram;
+class Q_DECLARATIVE_EXPORT QSimpleCanvasFilter : public QObject
+{
+Q_OBJECT
+public:
+ QSimpleCanvasFilter(QObject *parent);
+ virtual ~QSimpleCanvasFilter();
+
+ enum Layer { ChildrenUnderItem = 0x01,
+ Item = 0x02,
+ ChildrenAboveItem = 0x04,
+ All = 0x07 };
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ bool enabled() const;
+ void setEnabled(bool);
+
+ QSimpleCanvasItem *item() const;
+ void setItem(QSimpleCanvasItem *);
+Q_SIGNALS:
+ void enabledChanged();
+
+protected:
+
+ virtual QRectF itemBoundingRect(const QRectF &) const;
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+ virtual void filter(QPainter &p);
+
+ QGLFramebufferObject *renderToFBO(const QRectF &src = QRect(), const QPoint &offset = QPoint(), Layer = All);
+ QGLFramebufferObject *renderToFBO(float scale, const QRectF &src = QRect(), const QPoint &offset = QPoint(), Layer = All);
+ QGLFramebufferObject *acquireFBO(const QSize & = QSize());
+ void releaseFBO(QGLFramebufferObject *);
+
+ void renderToScreen(const QRectF &src = QRect(), Layer = All);
+ void renderToScreen(const QSimpleCanvas::Matrix &trans, const QRectF &src = QRect(), Layer = All);
+
+ void update();
+
+ bool isSimpleItem(QSimpleCanvasItem **, QSimpleCanvas::Matrix *);
+
+private:
+ friend class QSimpleCanvasFilterPrivate;
+ friend class QSimpleCanvasItemPrivate;
+ friend class QSimpleCanvasItem;
+
+ QSimpleCanvasFilterPrivate *d;
+};
+
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/canvas/qsimplecanvasfilter_p.h b/src/declarative/canvas/qsimplecanvasfilter_p.h
new file mode 100644
index 0000000..1c72993
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASFILTER_P_H
+#define QSIMPLECANVASFILTER_P_H
+
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleCanvasFilterPrivate
+{
+public:
+ QSimpleCanvasFilterPrivate(QSimpleCanvasFilter *_q)
+ : q(_q), item(0), enabled(true) {}
+
+ QSimpleCanvasFilter *q;
+
+ QSimpleCanvasItem *item;
+ bool enabled;
+#if defined(QFX_RENDER_OPENGL)
+ QSimpleCanvasItemPrivate::GLPaintParameters params;
+
+ void doFilterGL(QSimpleCanvasItem::GLPainter &, const QSimpleCanvasItemPrivate::GLPaintParameters &);
+
+ bool isSimpleItem(QSimpleCanvasItem *item, QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout);
+#endif
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp
new file mode 100644
index 0000000..f2222a9
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem.cpp
@@ -0,0 +1,1872 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas_p.h"
+#include <qfxitem.h>
+#include <QGraphicsSceneEvent>
+
+
+QT_BEGIN_NAMESPACE
+QSimpleCanvasItemData::QSimpleCanvasItemData()
+: buttons(Qt::NoButton), flip(QSimpleCanvasItem::NoFlip),
+ dirty(false), transformValid(true), doNotPaint(false),
+ doNotPaintChildren(false), x(0), y(0), z(0), visible(1),
+ transformUser(0), transformVersion(0), activeOpacity(1)
+{
+}
+
+QSimpleCanvasItemData::~QSimpleCanvasItemData()
+{
+ if (transformUser)
+ delete transformUser;
+}
+
+/*!
+ \internal
+ \class QSimpleCanvasItem
+ \brief The QSimpleCanvasItem class is the base class of canvas items.
+ */
+QSimpleCanvasLayer::QSimpleCanvasLayer()
+{
+}
+
+QSimpleCanvasLayer::QSimpleCanvasLayer(QSimpleCanvasItem *parent)
+: QSimpleCanvasItem(parent)
+{
+}
+
+void QSimpleCanvasLayer::addChild(QSimpleCanvasItem *c)
+{
+ QSimpleCanvasItem::addChild(c);
+}
+
+void QSimpleCanvasLayer::addDirty(QSimpleCanvasItem *)
+{
+}
+
+void QSimpleCanvasLayer::remDirty(QSimpleCanvasItem *)
+{
+}
+
+QSimpleCanvasLayer *QSimpleCanvasLayer::layer()
+{
+ return this;
+}
+
+QSimpleCanvasItem::Options QSimpleCanvasItem::options() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return (QSimpleCanvasItem::Options)d->options;
+}
+
+bool QSimpleCanvasItem::mouseFilter(QGraphicsSceneMouseEvent *)
+{
+ return false;
+}
+
+void QSimpleCanvasItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::hoverEnterEvent(QGraphicsSceneHoverEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseUngrabEvent()
+{
+}
+
+void QSimpleCanvasItem::keyPressEvent(QKeyEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::keyReleaseEvent(QKeyEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::focusOutEvent(QFocusEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::focusInEvent(QFocusEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::activePanelInEvent()
+{
+}
+
+void QSimpleCanvasItem::activePanelOutEvent()
+{
+}
+
+void QSimpleCanvasItem::inputMethodEvent(QInputMethodEvent *e)
+{
+ e->ignore();
+}
+
+QVariant QSimpleCanvasItem::inputMethodQuery(Qt::InputMethodQuery) const
+{
+ return QVariant();
+}
+
+void QSimpleCanvasItem::childrenChanged()
+{
+}
+
+void QSimpleCanvasItem::setPaintMargin(qreal margin)
+{
+ Q_D(QSimpleCanvasItem);
+ if (margin < d->paintmargin)
+ update(); // schedule repaint of old boundingRect
+ d->paintmargin = margin;
+}
+
+QRectF QSimpleCanvasItem::boundingRect() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return QRectF(-d->paintmargin, -d->paintmargin, d->width+d->paintmargin*2, d->height+d->paintmargin*2);
+}
+
+void QSimpleCanvasItem::paintContents(QPainter &)
+{
+}
+
+void QSimpleCanvasItem::paintGLContents(GLPainter &)
+{
+}
+
+uint QSimpleCanvasItem::glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count)
+{
+ Q_UNUSED(vertices);
+ Q_UNUSED(texVertices);
+ Q_UNUSED(texture);
+ Q_UNUSED(count);
+ return 0;
+}
+
+void QSimpleCanvasItem::canvasChanged()
+{
+}
+
+void QSimpleCanvasItem::focusChanged(bool)
+{
+}
+
+void QSimpleCanvasItem::activeFocusChanged(bool)
+{
+}
+
+void QSimpleCanvasItem::parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *)
+{
+}
+
+GLBasicShaders *QSimpleCanvasItem::basicShaders() const
+{
+#if defined(QFX_RENDER_OPENGL2)
+ return canvas()->d->basicShaders();
+#else
+ return 0;
+#endif
+}
+
+/*!
+ Returns the item's (0, 0) point relative to its parent.
+ */
+QPointF QSimpleCanvasItem::pos() const
+{
+ return QPointF(x(),y());
+}
+
+/*!
+ Returns the item's (0, 0) point mapped to scene coordinates.
+ */
+QPointF QSimpleCanvasItem::scenePos() const
+{
+ return mapToScene(QPointF(0, 0));
+}
+
+/*!
+ \enum QSimpleCanvasItem::TransformOrigin
+
+ Controls the point about which simple transforms like scale apply.
+
+ \value TopLeft The top-left corner of the item.
+ \value TopCenter The center point of the top of the item.
+ \value TopRight The top-right corner of the item.
+ \value MiddleLeft The left most point of the vertical middle.
+ \value Center The center of the item.
+ \value MiddleRight The right most point of the vertical middle.
+ \value BottomLeft The bottom-left corner of the item.
+ \value BottomCenter The center point of the bottom of the item.
+ \value BottomRight The bottom-right corner of the item.
+*/
+
+/*!
+ Returns the current transform origin.
+*/
+QSimpleCanvasItem::TransformOrigin QSimpleCanvasItem::transformOrigin() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->origin;
+}
+
+/*!
+ Set the transform \a origin.
+*/
+void QSimpleCanvasItem::setTransformOrigin(TransformOrigin origin)
+{
+ Q_D(QSimpleCanvasItem);
+ if (origin != d->origin) {
+ d->origin = origin;
+ update();
+ }
+}
+
+QPointF QSimpleCanvasItem::transformOriginPoint() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->transformOrigin();
+}
+
+/*!
+ Returns the canvas the item is on, or 0 if the item is not on a canvas.
+ */
+QSimpleCanvas *QSimpleCanvasItem::canvas() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->canvas;
+}
+
+/*!
+ Returns the parent if the item, or 0 if the item has no parent.
+ */
+QSimpleCanvasItem *QSimpleCanvasItem::parent() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->parent;
+}
+
+void QSimpleCanvasItemPrivate::zOrderChildren()
+{
+ if (!needsZOrder || children.count() <= 1)
+ return;
+
+ needsZOrder = false;
+ // This is a bubble sort for a reason - it is the fastest sort for a mostly
+ // ordered list. We only expect z ordering to change infrequently.
+ bool swap = true;
+ int c = 0;
+ while(swap) {
+ ++c;
+ swap = false;
+ QSimpleCanvasItem *item = children.first();
+ qreal z = item->z();
+ for (int ii = 1; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *i2 = children.at(ii);
+ qreal z2 = i2->z();
+ if (z2 < z) {
+ swap = true;
+ children[ii] = item;
+ children[ii - 1] = i2;
+ } else {
+ item = i2;
+ z = z2;
+ }
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::canvasChanged(QSimpleCanvas *newCanvas, QSimpleCanvas *oldCanvas)
+{
+ Q_Q(QSimpleCanvasItem);
+ canvas = newCanvas;
+ if (options & QSimpleCanvasItem::MouseFilter) {
+ if (oldCanvas) oldCanvas->d->removeMouseFilter(q);
+ if (newCanvas) newCanvas->d->installMouseFilter(q);
+ }
+ if (newCanvas) {
+ if (!oldCanvas && hasFocus)
+ newCanvas->d->setFocusItem(q, Qt::OtherFocusReason, false);
+ if (wantsActiveFocusPanelPendingCanvas) {
+ hasBeenActiveFocusPanel = true;
+ newCanvas->d->setActiveFocusPanel(q);
+ wantsActiveFocusPanelPendingCanvas = false;
+ }
+ }
+
+ for (int ii = 0; ii < children.count(); ++ii)
+ children.at(ii)->d_func()->canvasChanged(newCanvas, oldCanvas);
+ q->canvasChanged();
+}
+
+void QSimpleCanvasItem::setFocus(bool focus)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->hasFocus == focus)
+ return;
+ QSimpleCanvas *c = canvas();
+
+ if (c) {
+ if (focus)
+ c->d->setFocusItem(this, Qt::OtherFocusReason);
+ else
+ c->d->clearFocusItem(this);
+ } else {
+ d->setFocus(focus);
+ focusChanged(d->hasFocus);
+ }
+}
+
+qreal QSimpleCanvasItem::x() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->x();
+ else if (d->data_ptr)
+ return d->data()->x;
+ else
+ return 0;
+}
+
+qreal QSimpleCanvasItem::y() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->y();
+ else if (d->data_ptr)
+ return d->data()->y;
+ else
+ return 0;
+}
+
+qreal QSimpleCanvasItem::z() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->zValue();
+ else if (d->data_ptr)
+ return d->data()->z;
+ else
+ return 0;
+}
+
+void QSimpleCanvasItem::setX(qreal x)
+{
+ Q_D(QSimpleCanvasItem);
+ if (x == this->x())
+ return;
+
+ qreal oldX = this->x();
+
+ if (d->graphicsItem) {
+ d->graphicsItem->setPos(x, y());
+ } else {
+ d->data()->x = x;
+ update();
+ }
+
+ geometryChanged(QRectF(this->x(), y(), width(), height()),
+ QRectF(oldX, y(), width(), height()));
+}
+
+void QSimpleCanvasItem::setY(qreal y)
+{
+ Q_D(QSimpleCanvasItem);
+ if (y == this->y())
+ return;
+
+ qreal oldY = this->y();
+
+ if (d->graphicsItem) {
+ d->graphicsItem->setPos(x(), y);
+ } else {
+ d->data()->y = y;
+ update();
+ }
+
+ geometryChanged(QRectF(x(), this->y(), width(), height()),
+ QRectF(x(), oldY, width(), height()));
+}
+
+void QSimpleCanvasItem::setZ(qreal z)
+{
+ Q_D(QSimpleCanvasItem);
+ if (z == this->z())
+ return;
+
+ if (d->graphicsItem) {
+
+ if (z < 0)
+ d->graphicsItem->setFlag(QGraphicsItem::ItemStacksBehindParent,
+ true);
+ else
+ d->graphicsItem->setFlag(QGraphicsItem::ItemStacksBehindParent,
+ false);
+
+ d->graphicsItem->setZValue(z);
+
+ } else {
+ if (d->data()->z == z)
+ return;
+
+ d->data()->z = z;
+ if (parent())
+ static_cast<QSimpleCanvasItemPrivate*>(parent()->d_ptr)->needsZOrder = true;
+ update();
+ }
+}
+
+qreal QSimpleCanvasItem::width() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->width;
+}
+
+void QSimpleCanvasItem::setWidth(qreal w)
+{
+ Q_D(QSimpleCanvasItem);
+ d->widthValid = true;
+ if (d->width == w)
+ return;
+
+ qreal oldWidth = d->width;
+
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+void QSimpleCanvasItem::setImplicitWidth(qreal w)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->width == w || widthValid())
+ return;
+
+ qreal oldWidth = d->width;
+
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+bool QSimpleCanvasItem::widthValid() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->widthValid;
+}
+
+qreal QSimpleCanvasItem::height() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->height;
+}
+
+void QSimpleCanvasItem::setHeight(qreal h)
+{
+ Q_D(QSimpleCanvasItem);
+ d->heightValid = true;
+ if (d->height == h)
+ return;
+
+ qreal oldHeight = d->height;
+
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+void QSimpleCanvasItem::setImplicitHeight(qreal h)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->height == h || heightValid())
+ return;
+
+ qreal oldHeight = d->height;
+
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+bool QSimpleCanvasItem::heightValid() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->heightValid;
+}
+
+void QSimpleCanvasItem::setPos(const QPointF &point)
+{
+ Q_D(QSimpleCanvasItem);
+ qreal oldX = x();
+ qreal oldY = y();
+
+ if (d->graphicsItem) {
+ d->graphicsItem->setPos(point);
+ } else {
+ d->data()->x = point.x();
+ d->data()->y = point.y();
+ update();
+ }
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(oldX, oldY, width(), height()));
+}
+
+qreal QSimpleCanvasItem::scale() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->scale;
+}
+
+void QSimpleCanvasItem::setScale(qreal s)
+{
+ Q_D(QSimpleCanvasItem);
+ d->scale = s;
+ if (d->graphicsItem) {
+ QTransform t;
+ QPointF to = transformOriginPoint();
+ if (to.x() != 0. || to.y() != 0.)
+ t.translate(to.x(), to.y());
+ t.scale(s, s);
+ if (to.x() != 0. || to.y() != 0.)
+ t.translate(-to.x(), -to.y());
+ d->graphicsItem->setTransform(t * d->graphicsItem->transform);
+ } else {
+ update();
+ }
+}
+
+bool QSimpleCanvasItem::isVisible() const
+{
+ if (visible() <= 0)
+ return false;
+ else if (!parent())
+ return true;
+ else
+ return parent()->isVisible();
+}
+
+qreal QSimpleCanvasItem::visible() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->opacity();
+ else if (d->data_ptr)
+ return d->data()->visible;
+ else
+ return 1;
+}
+
+void QSimpleCanvasItem::setVisible(qreal v)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->setOpacity(v);
+ } else {
+ if (v == visible())
+ return;
+ if (v == 0)
+ update();
+
+ d->data()->visible = v;
+
+ if (v != 0)
+ update();
+ }
+}
+
+void QSimpleCanvasItem::addChild(QSimpleCanvasItem *c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->children.append(c);
+ if (!d->graphicsItem)
+ d->needsZOrder = true;
+ childrenChanged();
+}
+
+void QSimpleCanvasItem::remChild(QSimpleCanvasItem *c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->children.removeAll(c);
+ childrenChanged();
+}
+
+QSimpleCanvasFilter *QSimpleCanvasItem::filter() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->filter;
+}
+
+/*!
+QSimpleCanvasItem takes ownership of filter.
+*/
+void QSimpleCanvasItem::setFilter(QSimpleCanvasFilter *f)
+{
+ Q_D(QSimpleCanvasItem);
+ if (!d || f == d->filter)
+ return;
+
+ d->filter = f;
+ if (d->filter)
+ d->filter->setItem(this);
+ update();
+}
+
+const QList<QSimpleCanvasItem *> &QSimpleCanvasItem::children() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->children;
+}
+
+bool QSimpleCanvasItem::hasChildren() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return !d->children.isEmpty();
+}
+
+QSimpleCanvasLayer *QSimpleCanvasItem::layer()
+{
+ if (parent())
+ return parent()->layer();
+ else
+ return 0;
+}
+
+void QSimpleCanvasItem::update()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->update();
+ } else {
+ if (!parent())
+ return;
+
+ if (d->data()->dirty || 0. == d->data()->visible) return;
+
+ QSimpleCanvasLayer *l = layer();
+ if (l == this && parent())
+ l = parent()->layer();
+ if (l) {
+ l->addDirty(this);
+ d->data()->dirty = true;
+ d->data()->transformValid = false;
+ }
+ }
+}
+
+bool QSimpleCanvasItem::clip() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->clip;
+}
+
+void QSimpleCanvasItem::setClip(bool c)
+{
+ Q_D(const QSimpleCanvasItem);
+ if (bool(d->clip) == c)
+ return;
+
+ if (c)
+ setClipType(ClipToRect);
+ else
+ setClipType(NoClip);
+
+ update();
+}
+
+QSimpleCanvasItem::ClipType QSimpleCanvasItem::clipType() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->clip;
+}
+
+void QSimpleCanvasItem::setClipType(ClipType c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->clip = c;
+ if (d->graphicsItem)
+ d->graphicsItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, bool(c));
+ else
+ update();
+}
+
+Qt::MouseButtons QSimpleCanvasItem::acceptedMouseButtons() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->acceptedMouseButtons();
+ else if (d->data_ptr)
+ return (Qt::MouseButtons)d->data()->buttons;
+ else
+ return Qt::NoButton;
+}
+
+void QSimpleCanvasItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ d->graphicsItem->setAcceptedMouseButtons(buttons);
+ else
+ d->data()->buttons = buttons;
+}
+
+
+QRect QSimpleCanvasItem::itemBoundingRect()
+{
+ return boundingRect().toAlignedRect();
+}
+
+QPointF QSimpleCanvasItemPrivate::adjustFrom(const QPointF &p) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return p;
+
+ QPointF rv(-1. + 2. * p.x() / qreal(canvas->width()),
+ 1 - 2. * p.y() / qreal(canvas->height()));
+
+ return rv;
+#else
+ return p;
+#endif
+}
+
+QRectF QSimpleCanvasItemPrivate::adjustFrom(const QRectF &r) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return r;
+
+ qreal width = r.width() * 2. / qreal(canvas->width());
+ qreal height = r.height() * 2. / qreal(canvas->height());
+ qreal x = -1. + 2. * r.x() / qreal(canvas->width());
+ qreal y = 1. - 2. * r.y() / qreal(canvas->height()) - height;
+
+ return QRectF(x, y, width, height);
+#else
+ return r;
+#endif
+}
+
+QPointF QSimpleCanvasItemPrivate::adjustTo(const QPointF &p) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return p;
+
+ QPointF rv(0.5 * (p.x() + 1.) * qreal(canvas->width()),
+ 0.5 * (1. - p.y()) * qreal(canvas->height()));
+
+ return rv;
+#else
+ return p;
+#endif
+}
+
+QRectF QSimpleCanvasItemPrivate::adjustTo(const QRectF &r) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return r;
+
+ qreal width = 0.5 * r.width() * qreal(canvas->width());
+ qreal height = 0.5 * r.height() * qreal(canvas->height());
+ qreal x = 0.5 * (r.x() + 1.) * qreal(canvas->width());
+ qreal y = 0.5 * (1. - r.y()) * qreal(canvas->height()) - height;
+
+ return QRectF(x, y, width, height);
+#else
+ return r;
+#endif
+}
+
+QPointF QSimpleCanvasItem::mapFromScene(const QPointF &p) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapFromScene(p);
+ } else {
+ QPointF mp = d->adjustFrom(p);
+ d->freshenTransforms();
+#if defined(QFX_RENDER_OPENGL)
+ // m20X + m21Y + m22Z + m23 = 1
+ // Z = (1 - m23 - m20X - m21Y) / m22
+
+ QMatrix4x4 inv = d->data()->transformActive.inverted();
+ qreal z_s = (1 - inv(2,3) - inv(2,0) * mp.x() - inv(2, 1) * mp.y()) / inv(2, 2);
+
+ QVector3D vec(mp.x(), mp.y(), z_s);
+ QVector3D r = inv.map(vec);
+
+ return r.toPointF();
+#else
+ return d->data()->transformActive.inverted().map(mp);
+#endif
+ }
+}
+
+QRectF QSimpleCanvasItem::mapFromScene(const QRectF &r) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapFromScene(r).boundingRect();
+ } else {
+ QRectF mr = d->adjustFrom(r);
+ d->freshenTransforms();
+#if defined(QFX_RENDER_OPENGL)
+ // m20X + m21Y + m22Z + m23 = 1
+ // Z = (1 - m23 - m20X - m21Y) / m22
+
+ QMatrix4x4 inv = d->data()->transformActive.inverted();
+ qreal tl_z_s = (1 - inv(2,3) - inv(2,0) * mr.topLeft().x() - inv(2, 1) * mr.topLeft().y()) / inv(2, 2);
+ qreal tr_z_s = (1 - inv(2,3) - inv(2,0) * mr.topRight().x() - inv(2, 1) * mr.topRight().y()) / inv(2, 2);
+ qreal bl_z_s = (1 - inv(2,3) - inv(2,0) * mr.bottomLeft().x() - inv(2, 1) * mr.bottomLeft().y()) / inv(2, 2);
+ qreal br_z_s = (1 - inv(2,3) - inv(2,0) * mr.bottomRight().x() - inv(2, 1) * mr.bottomRight().y()) / inv(2, 2);
+
+ QVector3D tl(mr.topLeft().x(), mr.topLeft().y(), tl_z_s);
+ QVector3D tr(mr.topRight().x(), mr.topRight().y(), tr_z_s);
+ QVector3D bl(mr.bottomLeft().x(), mr.bottomLeft().y(), bl_z_s);
+ QVector3D br(mr.bottomRight().x(), mr.bottomRight().y(), br_z_s);
+
+ tl = inv.map(tl); tr = inv.map(tr); bl = inv.map(bl); br = inv.map(br);
+
+ qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
+#else
+ return d->data()->transformActive.inverted().mapRect(mr);
+#endif
+ }
+}
+
+QPointF QSimpleCanvasItem::mapToScene(const QPointF &p) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapToScene(p);
+ } else {
+ d->freshenTransforms();
+ QPointF rp = d->data()->transformActive.map(p);
+ return d->adjustTo(rp);
+ }
+}
+
+QRectF QSimpleCanvasItem::mapToScene(const QRectF &r) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapToScene(r).boundingRect();
+ } else {
+ d->freshenTransforms();
+ QRectF rr = d->data()->transformActive.mapRect(r);
+ return d->adjustTo(rr);
+ }
+}
+
+void QSimpleCanvasItemPrivate::freshenTransforms() const
+{
+ if (freshenNeeded())
+ doFreshenTransforms();
+}
+
+bool QSimpleCanvasItemPrivate::freshenNeeded() const
+{
+#if 0
+ return parent &&
+ (data()->transformVersion == -1 ||
+ data()->parentTransformVersion == -1 ||
+ parent->d_func()->data()->transformVersion != data()->parentTransformVersion);
+#else
+ const QSimpleCanvasItemPrivate *me = this;
+ while(me) {
+ if (me->data_ptr && !me->data_ptr->transformValid)
+ return true;
+ if (me->parent)
+ me = me->parent->d_func();
+ else
+ me = 0;
+ }
+ return false;
+#endif
+}
+
+void QSimpleCanvasItemPrivate::doFreshenTransforms() const
+{
+ Q_Q(const QSimpleCanvasItem);
+ if (parent)
+ parent->d_func()->doFreshenTransforms();
+
+ if (freshenNeeded()) {
+ if (parent)
+ data()->transformActive = parent->d_func()->data()->transformActive;
+ else
+ data()->transformActive = QSimpleCanvas::Matrix();
+ data()->transformActive.translate(q->x(), q->y());
+ if (scale != 1.) {
+ QPointF to = transformOrigin();
+ if (to.x() != 0. || to.y() != 0.)
+ data()->transformActive.translate(to.x(), to.y());
+ data()->transformActive.scale(scale, scale);
+ if (to.x() != 0. || to.y() != 0.)
+ data()->transformActive.translate(-to.x(), -to.y());
+ }
+
+ Q_Q(const QSimpleCanvasItem);
+#if defined(QFX_RENDER_OPENGL)
+ if (q->d_func()->data()->transformUser)
+ data()->transformActive *= *q->d_func()->data()->transformUser;
+#endif
+
+ if (data()->flip) {
+ QRectF br = q->boundingRect();
+ data()->transformActive.translate(br.width() / 2., br.height() / 2);
+#if defined(QFX_RENDER_OPENGL)
+ data()->transformActive.rotate(180, (data()->flip & QSimpleCanvasItem::VerticalFlip)?1:0, (data()->flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+#else
+ data()->transformActive.scale((data()->flip & QSimpleCanvasItem::HorizontalFlip)?-1:1,
+ (data()->flip & QSimpleCanvasItem::VerticalFlip)?-1:1);
+#endif
+ data()->transformActive.translate(-br.width() / 2., -br.height() / 2);
+ }
+ }
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItem::transform() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return QSimpleCanvasConfig::transformToMatrix(d->graphicsItem->transform);
+ else if (d->data()->transformUser)
+ return *d->data()->transformUser;
+ else
+ return QSimpleCanvas::Matrix();
+}
+
+void QSimpleCanvasItem::setTransform(const QSimpleCanvas::Matrix &m)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->transform = QSimpleCanvasConfig::matrixToTransform(m);
+ d->graphicsItem->setTransform(QTransform::fromScale(d->scale, d->scale) * d->graphicsItem->transform);
+ } else {
+ if (!d->data()->transformUser)
+ d->data()->transformUser = new QSimpleCanvas::Matrix;
+ *d->data()->transformUser = m;
+ update();
+ }
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::mouseGrabberItem() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ QGraphicsScene *s = d->graphicsItem->scene();
+ if (s) {
+ QGraphicsItem *item = s->mouseGrabberItem();
+ QSimpleGraphicsItem *dgi = static_cast<QSimpleGraphicsItem *>(item);
+ return dgi?static_cast<QSimpleCanvasItem*>(dgi->owner):0;
+ }
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c)
+ return c->d->lastMouseItem;
+ }
+ return 0;
+}
+
+void QSimpleCanvasItem::ungrabMouse()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->ungrabMouse();
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c && c->d->lastMouseItem == this) {
+ c->d->lastMouseItem->mouseUngrabEvent();
+ c->d->lastMouseItem = 0;
+ }
+ }
+}
+
+void QSimpleCanvasItem::grabMouse()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->grabMouse();
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c) {
+ if (c->d->lastMouseItem != this) {
+ if (c->d->lastMouseItem)
+ c->d->lastMouseItem->mouseUngrabEvent();
+ c->d->lastMouseItem = this;
+ }
+ }
+ }
+}
+
+bool QSimpleCanvasItem::isFocusable() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->focusable;
+}
+
+void QSimpleCanvasItem::setFocusable(bool f)
+{
+ Q_D(QSimpleCanvasItem);
+ d->focusable = f;
+}
+
+bool QSimpleCanvasItem::hasFocus() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->hasFocus;
+}
+
+void QSimpleCanvasItemPrivate::setFocus(bool f)
+{
+ hasFocus = f;
+}
+
+void QSimpleCanvasItemPrivate::setActiveFocus(bool f)
+{
+ hasActiveFocus = f;
+
+ if (graphicsItem) {
+ if (f) {
+ if (!(graphicsItem->flags() & QGraphicsItem::ItemIsFocusable))
+ graphicsItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ graphicsItem->setFocus();
+ } else {
+ graphicsItem->clearFocus();
+ if ((graphicsItem->flags() & QGraphicsItem::ItemIsFocusable) && !focusable)
+ graphicsItem->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ }
+
+ }
+}
+
+QSimpleCanvasItem::Flip QSimpleCanvasItem::flip() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return NoFlip;
+ else if (d->data_ptr)
+ return d->data()->flip;
+ else
+ return NoFlip;
+}
+
+void QSimpleCanvasItem::setFlip(Flip f)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return;
+
+ if (d->data()->flip == f)
+ return;
+
+ d->data()->flip = f;
+ update();
+}
+
+/*!
+ Places the item under \a item in the parent item's stack.
+
+ The item itself and \a item must be siblings, or this method has no effect.
+
+ \sa stackOver(), stackAt()
+ */
+void QSimpleCanvasItem::stackUnder(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if (!p || !item || item == this) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ int idx = parent_d_ptr->children.indexOf(item);
+ if (idx == -1) return;
+
+ parent_d_ptr->children.removeAll(this);
+ idx = parent_d_ptr->children.indexOf(item);
+ parent_d_ptr->children.insert(idx + 1, this);
+ parent_d_ptr->needsZOrder = true;
+
+ p->childrenChanged();
+}
+
+/*!
+ Places the item over \a item in the parent item's stack.
+
+ The item itself and \a item must be siblings, or this method has no effect.
+
+ \sa stackUnder(), stackAt()
+ */
+void QSimpleCanvasItem::stackOver(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if (!p || !item || item == this) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ int idx = parent_d_ptr->children.indexOf(item);
+ if (idx == -1) return;
+
+ parent_d_ptr->children.removeAll(this);
+ idx = parent_d_ptr->children.indexOf(item);
+ parent_d_ptr->children.insert(idx, this);
+ parent_d_ptr->needsZOrder = true;
+
+ p->childrenChanged();
+}
+
+/*!
+ Places the item at position \a index in the parent item's stack.
+
+ If index is zero or less, the item is placed at the beginning of the
+ stack. If the index is greater than the number of items in the stack, the
+ item is placed at the end.
+
+ \sa stackOver(), stackUnder()
+ */
+void QSimpleCanvasItem::stackAt(int index)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if (!p) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ parent_d_ptr->children.removeAll(this);
+
+ if (index < 0) index = 0;
+ if (index > parent_d_ptr->children.size()) index = parent_d_ptr->children.size();
+
+ parent_d_ptr->children.insert(index, this);
+ parent_d_ptr->needsZOrder = true;
+ p->childrenChanged();
+}
+
+/*!
+ Returns the current stacking index for the child \a item.
+
+ If \a item is not a child, -1 is returned.
+
+ \sa stackAt()
+ */
+int QSimpleCanvasItem::indexForChild(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ return d->children.indexOf(item);
+}
+
+bool QSimpleCanvasItem::eventFilter(QObject *o, QEvent *e)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ switch(e->type()) {
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ if (mouseFilter(static_cast<QGraphicsSceneMouseEvent *>(e)))
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return QObject::eventFilter(o, e);
+}
+
+void QSimpleCanvasItem::setOptions(Options options, bool set)
+{
+ Q_D(QSimpleCanvasItem);
+ Options old = (Options)d->options;
+
+ if (options & IsFocusPanel) {
+ if (!set) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot unset IsFocusPanel");
+ return;
+ } else if (hasChildren()) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot set IsFocusPanel once item has children");
+ return;
+ }
+ }
+
+ if (options & IsFocusRealm) {
+ if (!set) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot unset IsFocusRealm");
+ return;
+ }
+ }
+
+ if (set)
+ d->options |= options;
+ else
+ d->options &= ~options;
+
+ if ((d->options & IsFocusPanel) && (d->options & IsFocusRealm)) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot set both IsFocusPanel and IsFocusRealm. IsFocusRealm will be unset.");
+ d->options &= ~IsFocusRealm;
+ }
+
+ if ((old & MouseFilter) != (d->options & MouseFilter)) {
+ if (d->graphicsItem) {
+ if (d->options & MouseFilter)
+ d->gvAddMouseFilter();
+ else
+ d->gvRemoveMouseFilter();
+
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c) {
+ if (d->options & MouseFilter)
+ c->d->installMouseFilter(this);
+ else
+ c->d->removeMouseFilter(this);
+ }
+ }
+ }
+}
+
+QSimpleCanvasItem::QSimpleCanvasItem(QSimpleCanvasItemPrivate &dd, QSimpleCanvasItem *parent)
+: QObject(dd, parent)
+{
+}
+
+QSimpleCanvasItem::QSimpleCanvasItem(QSimpleCanvasItem *p)
+: QObject(*(new QSimpleCanvasItemPrivate), p)
+{
+}
+
+QSimpleCanvasItem::~QSimpleCanvasItem()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ if ((d->options & (IsFocusPanel|IsFocusRealm)) && d->canvas)
+ d->canvas->d->focusPanelData.remove(this);
+ if (d->hasFocus && d->canvas) {
+ QSimpleCanvasItem *prnt = parent();
+ while (prnt && !(prnt->options() & (IsFocusPanel|IsFocusRealm)))
+ prnt = prnt->parent();
+ if (prnt && d->canvas->d->focusPanelData.value(prnt) == this)
+ d->canvas->d->focusPanelData.remove(prnt);
+ }
+ if (d->filter)
+ delete d->filter;
+
+ qDeleteAll(children());
+ if (parent())
+ parent()->remChild(this);
+ delete d->graphicsItem;
+ } else {
+ update();
+ setOptions(MouseFilter, false);
+
+ if (d->canvas){
+ if (d->canvas->focusItem() == this)
+ d->canvas->d->focusItem = 0;
+ if (d->canvas->d->lastFocusItem == this)
+ d->canvas->d->lastFocusItem = 0;
+ if (d->hasBeenActiveFocusPanel)
+ d->canvas->d->clearFocusPanel(this);
+ if (d->hasFocus)
+ d->canvas->d->clearFocusItem(this);
+ }
+
+ while(!d->children.isEmpty()) {
+ QSimpleCanvasItem *child = d->children.takeFirst();
+ delete child;
+ }
+
+ delete d->filter;
+
+ if (parent() && d->data_ptr && d->data()->dirty) {
+ QSimpleCanvasLayer *l = parent()->layer();
+ if (l) {
+ l->remDirty(this);
+ }
+ }
+ if (d->parent)
+ d->parent->remChild(this);
+
+
+ if (d->data_ptr)
+ delete d->data_ptr;
+ }
+}
+
+QSimpleCanvasItem::operator QGraphicsItem *()
+{
+ Q_D(QSimpleCanvasItem);
+ if (!d->graphicsItem) {
+ if (parent()) {
+ qWarning("QSimpleCanvasItem: Only the root item can be converted into a QGraphicsItem");
+ return 0;
+ }
+ d->convertToGraphicsItem();
+ }
+ return d->graphicsItem;
+}
+
+QSimpleCanvasItem::operator QmlDebuggerStatus *()
+{
+ Q_D(QSimpleCanvasItem);
+ if(!d->debuggerStatus)
+ d->debuggerStatus = new QSimpleCanvasItemDebuggerStatus(this);
+ return d->debuggerStatus;
+}
+
+QPointF QSimpleCanvasItemPrivate::transformOrigin() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QRectF br = q->boundingRect();
+
+ switch(origin) {
+ default:
+ case QSimpleCanvasItem::TopLeft:
+ return QPointF(0, 0);
+ case QSimpleCanvasItem::TopCenter:
+ return QPointF(br.width() / 2., 0);
+ case QSimpleCanvasItem::TopRight:
+ return QPointF(br.width(), 0);
+ case QSimpleCanvasItem::MiddleLeft:
+ return QPointF(0, br.height() / 2.);
+ case QSimpleCanvasItem::Center:
+ return QPointF(br.width() / 2., br.height() / 2.);
+ case QSimpleCanvasItem::MiddleRight:
+ return QPointF(br.width(), br.height() / 2.);
+ case QSimpleCanvasItem::BottomLeft:
+ return QPointF(0, br.height());
+ case QSimpleCanvasItem::BottomCenter:
+ return QPointF(br.width() / 2., br.height());
+ case QSimpleCanvasItem::BottomRight:
+ return QPointF(br.width(), br.height());
+ }
+}
+
+void QSimpleCanvasItemPrivate::setParentInternal(QSimpleCanvasItem *p)
+{
+ Q_Q(QSimpleCanvasItem);
+ QSimpleCanvasItem *oldParent = parent;
+ if (graphicsItem) {
+ if (oldParent)
+ oldParent->remChild(q);
+
+ parent = p;
+ graphicsItem->setParentItem(p->d_func()->graphicsItem);
+
+ if (parent)
+ p->addChild(q);
+
+ } else {
+ bool canvasChange = false;
+ if (p)
+ canvasChange = (p->d_func()->canvas != canvas);
+ QSimpleCanvas *old = canvas;
+
+ QSimpleCanvasLayer *o = q->layer();
+ if (q->parent()) {
+ q->update();
+ q->parent()->remChild(q);
+ }
+ parent = p;
+ QSimpleCanvasLayer *n = 0;
+ if (q->parent()) {
+ q->parent()->addChild(q);
+ n = q->layer();
+ }
+
+ if (o != n) {
+ data()->dirty = false;
+ data()->transformValid = false;
+ if (o) o->remDirty(q);
+ if (n) n->addDirty(q);
+ }
+
+ if (canvasChange)
+ canvasChanged(p->d_func()->canvas, old);
+
+ q->update();
+ }
+}
+
+void QSimpleCanvasItemPrivate::convertToGraphicsItem(QGraphicsItem *parent)
+{
+ Q_Q(QSimpleCanvasItem);
+ Q_ASSERT(!graphicsItem);
+ graphicsItem = new QSimpleGraphicsItem(q);
+ if (parent)
+ graphicsItem->setParentItem(parent);
+
+ QSimpleCanvasItemData *old = data_ptr;
+ data_ptr = 0;
+
+ if (old) {
+ q->QSimpleCanvasItem::setX(old->x);
+ q->QSimpleCanvasItem::setY(old->y);
+ q->QSimpleCanvasItem::setZ(old->z);
+ q->QSimpleCanvasItem::setVisible(old->visible);
+ if (old->transformUser)
+ q->QSimpleCanvasItem::setTransform(*old->transformUser);
+ q->QSimpleCanvasItem::setFlip(old->flip);
+ q->QSimpleCanvasItem::setAcceptedMouseButtons((Qt::MouseButtons)old->buttons);
+ delete old;
+ }
+
+ if (scale != 1) {
+ qreal s = scale;
+ scale = 1;
+ q->QSimpleCanvasItem::setScale(s);
+ }
+
+ q->setClipType(clip);
+
+ for (int ii = 0; ii < children.count(); ++ii)
+ static_cast<QSimpleCanvasItemPrivate*>(children.at(ii)->d_ptr)->convertToGraphicsItem(graphicsItem);
+}
+
+/*!
+ \fn void QSimpleCanvasItem::setParent(QSimpleCanvasItem *parent)
+
+ Sets the parent of the item to \a parent.
+ */
+void QSimpleCanvasItem::setParent(QSimpleCanvasItem *p)
+{
+ Q_D(QSimpleCanvasItem);
+ if (p == parent() || !p) return;
+
+ QObject::setParent(p);
+
+ if (d->graphicsItem && !static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr)->graphicsItem)
+ qWarning("QSimpleCanvasItem: Cannot reparent a QGraphicsView item to a QSimpleCanvas item");
+
+ if (static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr)->graphicsItem && !d->graphicsItem) {
+ d->setParentInternal(0);
+ d->convertToGraphicsItem();
+ }
+
+ QSimpleCanvasItem *oldParent = d->parent;
+ d->setParentInternal(p);
+ parentChanged(p, oldParent);
+}
+
+int QSimpleCanvasItemPrivate::dump(int indent)
+{
+ Q_Q(QSimpleCanvasItem);
+ QByteArray ba(indent * 2, ' ');
+
+ QByteArray state;
+ if (options & QSimpleCanvasItem::MouseFilter)
+ state.append("i");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::HoverEvents)
+ state.append("h");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::MouseEvents)
+ state.append("m");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::HasContents)
+ state.append("c");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::SimpleItem)
+ state.append("s");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::IsFocusPanel) {
+ if (q->activeFocusPanel())
+ state.append("P");
+ else
+ state.append("p");
+ } else {
+ state.append("-");
+ }
+ if (options & QSimpleCanvasItem::IsFocusRealm)
+ state.append("r");
+ else
+ state.append("-");
+ if (q->hasFocus()) {
+ if (q->hasActiveFocus())
+ state.append("F");
+ else
+ state.append("f");
+ } else {
+ if (q->hasActiveFocus())
+ state.append("X");
+ else
+ state.append("-");
+ }
+
+ QByteArray name;
+ QFxItem *i = qobject_cast<QFxItem *>(q);
+ if (i)
+ name = i->id().toLatin1();
+ qWarning().nospace() << ba.constData() << state.constData() << " " << children.count() << " " << q << " " << name.constData();
+
+ int rv = 0;
+
+ for (int ii = 0; ii < children.count(); ++ii)
+ rv += children.at(ii)->d_func()->dump(indent + 1);
+
+ return rv + 1;
+}
+
+bool QSimpleCanvasItemPrivate::checkFocusState(FocusStateCheckDatas d,
+ FocusStateCheckRDatas *r)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ bool rv = true;
+ bool isRealm = (options & QSimpleCanvasItem::IsFocusPanel ||
+ options & QSimpleCanvasItem::IsFocusRealm);
+
+ if (options & QSimpleCanvasItem::IsFocusPanel) {
+
+ if (q->activeFocusPanel()) {
+ if (d & InActivePanel) {
+ qWarning() << "State ERROR: Nested active focus panels";
+ rv = false;
+ }
+
+ d |= InActivePanel;
+ } else {
+ d &= ~InActivePanel;
+ }
+
+ }
+
+ if (q->hasActiveFocus()) {
+ if (!(d & InActivePanel)) {
+ qWarning() << "State ERROR: Active focus in non-active panel";
+ rv = false;
+ }
+
+ if (d & InRealm && !(d & InActiveFocusedRealm)) {
+ qWarning() << "State ERROR: Active focus in non-active-focused realm";
+ rv = false;
+ }
+
+ if (!q->hasFocus()) {
+ qWarning() << "State ERROR: Active focus on element that does not have focus";
+ rv = false;
+ }
+
+ if (*r & SeenActiveFocus) {
+ qWarning() << "State ERROR: Two active focused elements in same realm";
+ rv = false;
+ }
+
+ *r |= SeenActiveFocus;
+ }
+
+ if (q->hasFocus()) {
+ if (*r & SeenFocus) {
+ qWarning() << "State ERROR: Two focused elements in same realm";
+ rv = false;
+ }
+
+ *r |= SeenFocus;
+ }
+
+ if (options & QSimpleCanvasItem::IsFocusRealm) {
+ d |= InRealm;
+
+ if (q->hasActiveFocus())
+ d |= InActiveFocusedRealm;
+ else
+ d &= ~InActiveFocusedRealm;
+ }
+
+ FocusStateCheckRDatas newR = NoCheckRData;
+ if (isRealm)
+ r = &newR;
+
+ for (int ii = 0; ii < children.count(); ++ii)
+ rv &= children.at(ii)->d_func()->checkFocusState(d, r);
+
+ return rv;
+}
+
+bool QSimpleCanvasItem::activeFocusPanel() const
+{
+ QSimpleCanvas *c = canvas();
+ if (!c) {
+ Q_D(const QSimpleCanvasItem);
+ return d->wantsActiveFocusPanelPendingCanvas;
+ } else {
+ return c->activeFocusPanel() == this;
+ }
+}
+
+void QSimpleCanvasItem::setActiveFocusPanel(bool b)
+{
+ if (!(options() & IsFocusPanel)) {
+ qWarning("QSimpleCanvasItem::setActiveFocusPanel: Item is not a focus panel");
+ return;
+ }
+
+ QSimpleCanvas *c = canvas();
+ Q_D(QSimpleCanvasItem);
+ if (c) {
+ if (b) {
+ d->hasBeenActiveFocusPanel = true;
+ c->d->setActiveFocusPanel(this);
+ } else if (d->hasBeenActiveFocusPanel) {
+ d->hasBeenActiveFocusPanel = false;
+ c->d->clearFocusPanel(this);
+ }
+ } else {
+ d->wantsActiveFocusPanelPendingCanvas = b;
+ }
+}
+
+bool QSimpleCanvasItem::hasActiveFocus() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->hasActiveFocus;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findFirstFocusChild() const
+{
+ Q_D(const QSimpleCanvasItem);
+
+ const QList<QSimpleCanvasItem *> &children = d->children;
+
+ for (int i = 0; i < children.count(); ++i) {
+ QSimpleCanvasItem *child = children.at(i);
+ if (child->options() & IsFocusPanel)
+ continue;
+
+ if (child->isFocusable())
+ return child;
+
+ QSimpleCanvasItem *testFocus = child->findFirstFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findLastFocusChild() const
+{
+ Q_D(const QSimpleCanvasItem);
+
+ const QList<QSimpleCanvasItem *> &children = d->children;
+
+ for (int i = children.count()-1; i >= 0; --i) {
+ QSimpleCanvasItem *child = children.at(i);
+ if (child->options() & IsFocusPanel)
+ continue;
+
+ if (child->isFocusable())
+ return child;
+ QSimpleCanvasItem *testFocus = child->findLastFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findPrevFocus(QSimpleCanvasItem *item)
+{
+ QSimpleCanvasItem *focusChild = item->findLastFocusChild();
+ if (focusChild)
+ return focusChild;
+
+ if (item->options() & IsFocusPanel) {
+ if (item->isFocusable())
+ return item;
+ else
+ return 0;
+ }
+
+ QSimpleCanvasItem *parent = item->parent();
+ while (parent) {
+ const QList<QSimpleCanvasItem *> &children = parent->d_func()->children;
+
+ int idx = children.indexOf(item);
+ QSimpleCanvasItem *testFocus = 0;
+ if (idx > 0) {
+ while (--idx >= 0) {
+ testFocus = children.at(idx);
+ if (testFocus->options() & IsFocusPanel)
+ continue;
+ if (testFocus->isFocusable())
+ return testFocus;
+ testFocus = testFocus->findLastFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+ }
+ if (parent->options() & IsFocusPanel) {
+ if (parent->isFocusable())
+ return parent;
+ else
+ return 0;
+ }
+ item = parent;
+ parent = parent->parent();
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findNextFocus(QSimpleCanvasItem *item)
+{
+ QSimpleCanvasItem *focusChild = item->findFirstFocusChild();
+ if (focusChild)
+ return focusChild;
+
+ if (item->options() & IsFocusPanel) {
+ if (item->isFocusable())
+ return item;
+ else
+ return 0;
+ }
+
+ QSimpleCanvasItem *parent = item->parent();
+ while (parent) {
+ const QList<QSimpleCanvasItem *> &children = parent->d_func()->children;
+
+ int idx = children.indexOf(item);
+ QSimpleCanvasItem *testFocus = 0;
+ if (idx >= 0) {
+ while (++idx < children.count()) {
+ testFocus = children.at(idx);
+ if (testFocus->options() & IsFocusPanel)
+ continue;
+ if (testFocus->isFocusable())
+ return testFocus;
+ testFocus = testFocus->findFirstFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+ }
+ if (parent->options() & IsFocusPanel) {
+ if (parent->isFocusable())
+ return parent;
+ else
+ return 0;
+ }
+ item = parent;
+ parent = parent->parent();
+ }
+
+ return 0;
+}
+
+QPixmap QSimpleCanvasItem::string(const QString &str, const QColor &c, const QFont &f)
+{
+ QFontMetrics fm(f);
+ QSize size(fm.width(str), fm.height()*(str.count(QLatin1Char('\n'))+1)); //fm.boundingRect(str).size();
+ QPixmap img(size);
+ img.fill(Qt::transparent);
+ QPainter p(&img);
+ p.setPen(c);
+ p.setFont(f);
+ p.drawText(img.rect(), Qt::AlignVCenter, str);
+ return img;
+}
+
+void QSimpleCanvasItem::geometryChanged(const QRectF &, const QRectF &)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h
new file mode 100644
index 0000000..f817799
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem.h
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASITEM_H
+#define QSIMPLECANVASITEM_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmldebuggerstatus.h>
+#include <QtDeclarative/qsimplecanvas.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qgraphicsitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QPainter;
+class QRect;
+class QSimpleCanvas;
+class QMouseEvent;
+class QKeyEvent;
+class QSimpleCanvasItemPrivate;
+class QSimpleCanvasLayer;
+class QPointF;
+class QRectF;
+class QGraphicsSceneHoverEvent;
+class QSimpleCanvasFilter;
+class GLTexture;
+class QGLShaderProgram;
+
+class Q_DECLARATIVE_EXPORT QSimpleCanvasItem : public QObject
+{
+ Q_OBJECT
+ Q_CAST_INTERFACES(QGraphicsItem)
+ Q_CAST_INTERFACES(QmlDebuggerStatus)
+ Q_DECLARE_PRIVATE(QSimpleCanvasItem)
+ Q_ENUMS(TransformOrigin)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin)
+
+public:
+ enum ClipType { NoClip = 0x00,
+ ClipToHeight = 0x01,
+ ClipToWidth = 0x02,
+ ClipToRect = 0x03 };
+ enum Option { NoOption = 0x00000000,
+ MouseFilter = 0x00000001,
+ ChildMouseFilter = 0x00000002,
+ HoverEvents = 0x00000004,
+ MouseEvents = 0x00000008,
+ HasContents = 0x00000010,
+ SimpleItem = 0x00000020,
+ IsFocusPanel = 0x00000040,
+ IsFocusRealm = 0x00000080,
+ AcceptsInputMethods = 0x00000100};
+ Q_DECLARE_FLAGS(Options, Option)
+
+ QSimpleCanvasItem(QSimpleCanvasItem *parent=0);
+ virtual ~QSimpleCanvasItem();
+ operator QGraphicsItem *();
+ operator QmlDebuggerStatus *();
+
+ bool clip() const;
+ void setClip(bool);
+ ClipType clipType() const;
+ void setClipType(ClipType);
+
+ Options options() const;
+ void setOptions(Options, bool set = true);
+
+ Qt::MouseButtons acceptedMouseButtons() const;
+ void setAcceptedMouseButtons(Qt::MouseButtons buttons);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ QPointF pos() const;
+ void setX(qreal);
+ void setY(qreal);
+ virtual void setZ(qreal);
+ void setPos(const QPointF &);
+
+ qreal width() const;
+ void setWidth(qreal);
+ void setImplicitWidth(qreal);
+ bool widthValid() const;
+ qreal height() const;
+ void setHeight(qreal);
+ void setImplicitHeight(qreal);
+ bool heightValid() const;
+
+ QPointF scenePos() const;
+
+ enum TransformOrigin {
+ TopLeft, TopCenter, TopRight,
+ MiddleLeft, Center, MiddleRight,
+ BottomLeft, BottomCenter, BottomRight
+ };
+ TransformOrigin transformOrigin() const;
+ void setTransformOrigin(TransformOrigin);
+ QPointF transformOriginPoint() const;
+
+
+ qreal scale() const;
+ virtual void setScale(qreal);
+
+ enum Flip { NoFlip = 0,
+ VerticalFlip = 0x01,
+ HorizontalFlip = 0x02,
+ VerticalAndHorizontalFlip = 0x03 };
+ Flip flip() const;
+ void setFlip(Flip);
+
+ qreal visible() const;
+ virtual void setVisible(qreal);
+ bool isVisible() const;
+
+ QSimpleCanvas *canvas() const;
+
+ QSimpleCanvasItem *parent() const;
+ void setParent(QSimpleCanvasItem *);
+ void stackUnder(QSimpleCanvasItem *);
+ void stackOver(QSimpleCanvasItem *);
+ void stackAt(int idx);
+ int indexForChild(QSimpleCanvasItem *);
+
+ QRect itemBoundingRect();
+
+ class GLPainter
+ {
+ public:
+ GLPainter(QSimpleCanvasItem *i) : item(i), activeOpacity(1) {}
+ QSimpleCanvasItem *item;
+ QSimpleCanvas::Matrix activeTransform;
+ qreal activeOpacity;
+ QRect sceneClipRect;
+
+ QGLShaderProgram *useTextureShader();
+ QGLShaderProgram *useColorShader(const QColor &);
+ void drawPixmap(const QPointF &, const GLTexture &);
+ void drawPixmap(const QRectF &, const GLTexture &);
+ private:
+ GLPainter(const GLPainter &);
+ GLPainter &operator=(const GLPainter &);
+ };
+
+
+ void setPaintMargin(qreal margin);
+ QRectF boundingRect() const;
+ virtual void paintContents(QPainter &);
+ virtual void paintGLContents(GLPainter &);
+ virtual uint glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count);
+
+ void update();
+
+ virtual QSimpleCanvasLayer *layer();
+
+ bool hasChildren() const;
+ const QList<QSimpleCanvasItem *> &children() const;
+
+ QPointF mapFromScene(const QPointF &) const;
+ QRectF mapFromScene(const QRectF &) const;
+ QPointF mapToScene(const QPointF &) const;
+ QRectF mapToScene(const QRectF &) const;
+
+ QSimpleCanvas::Matrix transform() const;
+ void setTransform(const QSimpleCanvas::Matrix &);
+
+ QSimpleCanvasFilter *filter() const;
+ void setFilter(QSimpleCanvasFilter *);
+
+ QSimpleCanvasItem *mouseGrabberItem() const;
+ void ungrabMouse();
+ void grabMouse();
+
+ virtual bool isFocusable() const;
+ void setFocusable(bool);
+ virtual bool hasFocus() const;
+ void setFocus(bool);
+ bool activeFocusPanel() const;
+ void setActiveFocusPanel(bool);
+
+ bool hasActiveFocus() const;
+
+ QSimpleCanvasItem *findFirstFocusChild() const;
+ QSimpleCanvasItem *findLastFocusChild() const;
+ static QSimpleCanvasItem *findPrevFocus(QSimpleCanvasItem *item);
+ static QSimpleCanvasItem *findNextFocus(QSimpleCanvasItem *item);
+
+ GLBasicShaders *basicShaders() const;
+
+ static QPixmap string(const QString &, const QColor & = Qt::black, const QFont & = QFont());
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual void addChild(QSimpleCanvasItem *);
+ virtual void remChild(QSimpleCanvasItem *);
+ virtual void canvasChanged();
+ virtual void childrenChanged();
+ virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *);
+ virtual void focusChanged(bool);
+ virtual void activeFocusChanged(bool);
+ virtual bool eventFilter(QObject *, QEvent *);
+
+public:
+ // Events
+ virtual bool mouseFilter(QGraphicsSceneMouseEvent *);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *);
+ virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseUngrabEvent();
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void focusOutEvent(QFocusEvent *e);
+ virtual void focusInEvent(QFocusEvent *e);
+ virtual void activePanelInEvent();
+ virtual void activePanelOutEvent();
+ virtual void inputMethodEvent(QInputMethodEvent* event);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+private:
+ friend class QSimpleCanvas;
+ friend class QSimpleCanvasPrivate;
+ friend class QSimpleCanvasRootLayer;
+ friend class QSimpleCanvasItem::GLPainter;
+ friend class QSimpleCanvasFilter;
+ friend class QGraphicsQSimpleCanvasItem;
+ friend class QSimpleGraphicsItem;
+ friend class CanvasEGLWidget;
+ friend class QSimpleCanvasFilterPrivate;
+
+public:
+ QSimpleCanvasItem(QSimpleCanvasItemPrivate &dd, QSimpleCanvasItem *parent);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItem::Options)
+
+class QSimpleCanvasLayer : public QSimpleCanvasItem
+{
+public:
+ QSimpleCanvasLayer(QSimpleCanvasItem *parent);
+
+ virtual void addChild(QSimpleCanvasItem *);
+ virtual void addDirty(QSimpleCanvasItem *);
+ virtual void remDirty(QSimpleCanvasItem *);
+ virtual QSimpleCanvasLayer *layer();
+
+private:
+ friend class QSimpleCanvas;
+ friend class QSimpleCanvasRootLayer;
+ QSimpleCanvasLayer();
+};
+
+
+
+#endif // _GFXCANVASITEM_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h
new file mode 100644
index 0000000..e2deab2
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem_p.h
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASITEM_P_H
+#define QSIMPLECANVASITEM_P_H
+
+#include "private/qobject_p.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasfilter.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glbasicshaders.h>
+#endif
+
+#include "qgraphicsitem.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleGraphicsItem : public QGraphicsItem
+{
+public:
+ QSimpleGraphicsItem(QSimpleCanvasItem *);
+ virtual ~QSimpleGraphicsItem();
+
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ virtual QRectF boundingRect() const;
+
+ QTransform transform;
+protected:
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual bool sceneEvent(QEvent *);
+ virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void focusInEvent(QFocusEvent *event);
+
+private:
+ friend class QSimpleCanvasItem;
+ QSimpleCanvasItem *owner;
+};
+
+class QSimpleCanvasItemData
+{
+public:
+ QSimpleCanvasItemData();
+ ~QSimpleCanvasItemData();
+
+ // 5 bits is all that's needed to store Qt::MouseButtons
+ int buttons:5;
+ QSimpleCanvasItem::Flip flip:2;
+ bool dirty:1;
+ bool transformValid:1;
+ bool doNotPaint:1;
+ bool doNotPaintChildren:1;
+
+ qreal x;
+ qreal y;
+ qreal z;
+ float visible;
+
+ QSimpleCanvas::Matrix *transformUser;
+ QSimpleCanvas::Matrix transformActive;
+ int transformVersion;
+
+ float activeOpacity;
+
+#if defined(QFX_RENDER_OPENGL)
+ QRectF lastPaintRect;
+#else
+ QRect lastPaintRect;
+#endif
+};
+
+class QSimpleCanvasItemDebuggerStatus : public QmlDebuggerStatus
+{
+public:
+ QSimpleCanvasItemDebuggerStatus(QSimpleCanvasItem *i)
+ : item(i), selected(false) {}
+
+ virtual void setSelectedState(bool state)
+ {
+ selected = state;
+ item->update();
+ }
+
+ QSimpleCanvasItem *item;
+ bool selected;
+};
+
+class QSimpleCanvasFilter;
+class QGraphicsQSimpleCanvasItem;
+class QSimpleCanvasItemPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSimpleCanvasItem)
+public:
+ QSimpleCanvasItemPrivate()
+ : parent(0), canvas(0), debuggerStatus(0), filter(0),
+ clip(QSimpleCanvasItem::NoClip),
+ origin(QSimpleCanvasItem::TopLeft), options(QSimpleCanvasItem::NoOption),
+ focusable(false), wantsActiveFocusPanelPendingCanvas(false),
+ hasBeenActiveFocusPanel(false),
+ hasFocus(false), hasActiveFocus(false), needsZOrder(false),
+ widthValid(false), heightValid(false), width(0), height(0), paintmargin(0), scale(1),
+ graphicsItem(0), data_ptr(0)
+ {
+ }
+
+ virtual ~QSimpleCanvasItemPrivate()
+ {
+ if(debuggerStatus) delete debuggerStatus;
+ }
+
+ QSimpleCanvasItem *parent;
+ QSimpleCanvas *canvas;
+ QList<QSimpleCanvasItem *> children;
+
+ QSimpleCanvasItemDebuggerStatus *debuggerStatus;
+ QSimpleCanvasFilter *filter;
+
+ QSimpleCanvasItem::ClipType clip:3;
+ QSimpleCanvasItem::TransformOrigin origin:4;
+ int options:9;
+ bool focusable:1;
+ bool wantsActiveFocusPanelPendingCanvas:1;
+ bool hasBeenActiveFocusPanel:1;
+ bool hasFocus:1;
+ bool hasActiveFocus:1;
+ bool needsZOrder:1;
+ bool widthValid:1;
+ bool heightValid:1;
+
+ void setFocus(bool f);
+ void setActiveFocus(bool f);
+
+ qreal width;
+ qreal height;
+ qreal paintmargin;
+ qreal scale;
+
+ QSimpleGraphicsItem *graphicsItem;
+ inline QSimpleCanvasItemData *data() const {
+ if (!data_ptr) data_ptr = new QSimpleCanvasItemData;
+ return data_ptr;
+ }
+ mutable QSimpleCanvasItemData *data_ptr;
+
+ void gvRemoveMouseFilter();
+ void gvAddMouseFilter();
+
+ void canvasChanged(QSimpleCanvas *newCanvas, QSimpleCanvas *oldCanvas);
+
+ void freshenTransforms() const;
+
+ QPointF adjustFrom(const QPointF &) const;
+ QRectF adjustFrom(const QRectF &) const;
+ QPointF adjustTo(const QPointF &) const;
+ QRectF adjustTo(const QRectF &) const;
+
+ QPointF transformOrigin() const;
+
+ void setParentInternal(QSimpleCanvasItem *);
+ void convertToGraphicsItem(QGraphicsItem * = 0);
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paint(QPainter &);
+ void paintChild(QPainter &, QSimpleCanvasItem *);
+ QRect setupPainting(int version, const QRect &bounding);
+#else
+ struct GLPaintParameters
+ {
+ QRect sceneRect;
+ QRectF boundingRect;
+ QRect clipRect;
+#if defined(QFX_RENDER_OPENGL2)
+ uchar stencilValue;
+#endif
+ float opacity;
+ bool forceParamRefresh;
+ };
+#if defined(QFX_RENDER_OPENGL2)
+ QRectF setupPainting(int version, const QRect &bounding);
+#elif defined(QFX_RENDER_OPENGL1)
+ QRectF setupPainting(int version, const QRect &bounding, unsigned int *zero);
+#endif
+ void setupChildState(QSimpleCanvasItem *);
+
+ void paint(GLPaintParameters &, QSimpleCanvasFilter::Layer = QSimpleCanvasFilter::All);
+#if defined(QFX_RENDER_OPENGL1)
+ void paintNoClip(GLPaintParameters &, QSimpleCanvasFilter::Layer = QSimpleCanvasFilter::All);
+#endif
+ void paintChild(const GLPaintParameters &, QSimpleCanvasItem *);
+ void simplePaintChild(const GLPaintParameters &, QSimpleCanvasItem *);
+
+ inline GLBasicShaders *basicShaders() const;
+
+ QSimpleCanvas::Matrix localTransform() const;
+
+#endif
+
+ void zOrderChildren();
+ bool freshenNeeded() const;
+ void doFreshenTransforms() const;
+
+ // Debugging
+ int dump(int);
+ enum FocusStateCheckData { NoCheckData = 0x00,
+ InActivePanel = 0x01,
+ InRealm = 0x02,
+ InActiveFocusedRealm = 0x04
+ };
+ Q_DECLARE_FLAGS(FocusStateCheckDatas, FocusStateCheckData)
+ enum FocusStateCheckRData { NoCheckRData = 0x00,
+ SeenFocus = 0x01,
+ SeenActiveFocus = 0x02 };
+ Q_DECLARE_FLAGS(FocusStateCheckRDatas, FocusStateCheckRData)
+ bool checkFocusState(FocusStateCheckDatas, FocusStateCheckRDatas *);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItemPrivate::FocusStateCheckDatas)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItemPrivate::FocusStateCheckRDatas)
+
+#endif // QSIMPLECANVASITEM_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
new file mode 100644
index 0000000..aa36675
--- /dev/null
+++ b/src/declarative/debugger/debugger.pri
@@ -0,0 +1,17 @@
+SOURCES += debugger/qmldebugger.cpp \
+ debugger/qmldebuggerstatus.cpp \
+ debugger/qmlpropertyview.cpp \
+ debugger/qmlwatches.cpp \
+ debugger/qmlobjecttree.cpp \
+ debugger/qpacketprotocol.cpp \
+ debugger/qmldebugserver.cpp \
+ debugger/qmldebugclient.cpp
+
+HEADERS += debugger/qmldebugger.h \
+ debugger/qmldebuggerstatus.h \
+ debugger/qmlpropertyview_p.h \
+ debugger/qmlwatches_p.h \
+ debugger/qmlobjecttree_p.h \
+ debugger/qpacketprotocol.h \
+ debugger/qmldebugserver.h \
+ debugger/qmldebugclient.h
diff --git a/src/declarative/debugger/qmldebugclient.cpp b/src/declarative/debugger/qmldebugclient.cpp
new file mode 100644
index 0000000..3dacf01
--- /dev/null
+++ b/src/declarative/debugger/qmldebugclient.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebugclient.h"
+#include <private/qobject_p.h>
+#include <QtDeclarative/qpacketprotocol.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlDebugClientPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QmlDebugClientPrivate(QmlDebugClient *c);
+ QmlDebugClient *q;
+ QPacketProtocol *protocol;
+
+ QStringList enabled;
+ QHash<QString, QmlDebugClientPlugin *> plugins;
+public slots:
+ void connected();
+ void readyRead();
+};
+
+QmlDebugClientPrivate::QmlDebugClientPrivate(QmlDebugClient *c)
+: QObject(c), q(c), protocol(0)
+{
+ protocol = new QPacketProtocol(q, this);
+ QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
+ QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void QmlDebugClientPrivate::connected()
+{
+ QPacket pack;
+ pack << QString(QLatin1String("QmlDebugServer")) << enabled;
+ protocol->send(pack);
+}
+
+void QmlDebugClientPrivate::readyRead()
+{
+ QPacket pack = protocol->read();
+ QString name; QByteArray message;
+ pack >> name >> message;
+
+ QHash<QString, QmlDebugClientPlugin *>::Iterator iter =
+ plugins.find(name);
+ if (iter == plugins.end()) {
+ qWarning() << "QmlDebugClient: Message received for missing plugin" << name;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+}
+
+QmlDebugClient::QmlDebugClient(QObject *parent)
+: QTcpSocket(parent), d(new QmlDebugClientPrivate(this))
+{
+}
+
+class QmlDebugClientPluginPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDebugClientPlugin);
+public:
+ QmlDebugClientPluginPrivate();
+
+ QString name;
+ QmlDebugClient *client;
+ bool enabled;
+};
+
+QmlDebugClientPluginPrivate::QmlDebugClientPluginPrivate()
+: client(0), enabled(false)
+{
+}
+
+QmlDebugClientPlugin::QmlDebugClientPlugin(const QString &name,
+ QmlDebugClient *parent)
+: QObject(*(new QmlDebugClientPluginPrivate), parent)
+{
+ Q_D(QmlDebugClientPlugin);
+ d->name = name;
+ d->client = parent;
+
+ if (!d->client)
+ return;
+
+ if (d->client->d->plugins.contains(name)) {
+ qWarning() << "QmlDebugClientPlugin: Conflicting plugin name" << name;
+ d->client = 0;
+ } else {
+ d->client->d->plugins.insert(name, this);
+ }
+}
+
+QString QmlDebugClientPlugin::name() const
+{
+ Q_D(const QmlDebugClientPlugin);
+ return d->name;
+}
+
+bool QmlDebugClientPlugin::isEnabled() const
+{
+ Q_D(const QmlDebugClientPlugin);
+ return d->enabled;
+}
+
+void QmlDebugClientPlugin::setEnabled(bool e)
+{
+ Q_D(QmlDebugClientPlugin);
+ if (e == d->enabled)
+ return;
+
+ d->enabled = e;
+
+ if (d->client) {
+ if (e)
+ d->client->d->enabled.append(d->name);
+ else
+ d->client->d->enabled.removeAll(d->name);
+
+ if (d->client->state() == QTcpSocket::ConnectedState) {
+ QPacket pack;
+ pack << QString(QLatin1String("QmlDebugServer"));
+ if (e) pack << (int)1;
+ else pack << (int)2;
+ pack << d->name;
+ d->client->d->protocol->send(pack);
+ }
+ }
+}
+
+void QmlDebugClientPlugin::sendMessage(const QByteArray &message)
+{
+ Q_D(QmlDebugClientPlugin);
+
+ if (!d->client || d->client->state() != QTcpSocket::ConnectedState)
+ return;
+
+ QPacket pack;
+ pack << d->name << message;
+ d->client->d->protocol->send(pack);
+}
+
+void QmlDebugClientPlugin::messageReceived(const QByteArray &)
+{
+}
+
+#include "qmldebugclient.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebugclient.h b/src/declarative/debugger/qmldebugclient.h
new file mode 100644
index 0000000..3fbf534
--- /dev/null
+++ b/src/declarative/debugger/qmldebugclient.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGCLIENT_H
+#define QMLDEBUGCLIENT_H
+
+#include <QtNetwork/qtcpsocket.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlDebugClientPrivate;
+class Q_DECLARATIVE_EXPORT QmlDebugClient : public QTcpSocket
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QmlDebugClient)
+public:
+ QmlDebugClient(QObject * = 0);
+
+private:
+ QmlDebugClientPrivate *d;
+ friend class QmlDebugClientPlugin;
+ friend class QmlDebugClientPluginPrivate;
+};
+
+class QmlDebugClientPluginPrivate;
+class Q_DECLARATIVE_EXPORT QmlDebugClientPlugin : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlDebugClientPlugin)
+ Q_DISABLE_COPY(QmlDebugClientPlugin)
+
+public:
+ QmlDebugClientPlugin(const QString &, QmlDebugClient *parent);
+
+ QString name() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ void sendMessage(const QByteArray &);
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ friend class QmlDebugClient;
+ friend class QmlDebugClientPrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDEBUGCLIENT_H
diff --git a/src/declarative/debugger/qmldebugger.cpp b/src/declarative/debugger/qmldebugger.cpp
new file mode 100644
index 0000000..9ab3247
--- /dev/null
+++ b/src/declarative/debugger/qmldebugger.cpp
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebugger.h"
+#include <QtGui/qtreewidget.h>
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qplaintextedit.h>
+#include <QTextBlock>
+#include <QtGui/qtabwidget.h>
+#include <QtDeclarative/qmlbindablevalue.h>
+#include <QtDeclarative/qmldebuggerstatus.h>
+#include <private/qmlboundsignal_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlobjecttree_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qsplitter.h>
+#include <QtGui/qpushbutton.h>
+#include <QtGui/qtablewidget.h>
+#include <QtGui/qevent.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <private/qmlpropertyview_p.h>
+#include <private/qmlwatches_p.h>
+
+QmlDebugger::QmlDebugger(QWidget *parent)
+: QWidget(parent), m_tree(0), m_warnings(0), m_watchTable(0), m_watches(0),
+ m_properties(0), m_text(0), m_highlightedItem(0)
+{
+ QHBoxLayout *layout = new QHBoxLayout;
+ setLayout(layout);
+ QSplitter *splitter = new QSplitter(this);
+ layout->addWidget(splitter);
+
+ QWidget *treeWid = new QWidget(this);
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->setContentsMargins(0, 0, 0, 0);
+ treeWid->setLayout(vlayout);
+ splitter->addWidget(treeWid);
+
+ m_tree = new QmlObjectTree(treeWid);
+ m_tree->setHeaderHidden(true);
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(addWatch(QObject*,QString)), this, SLOT(addWatch(QObject*,QString)));
+ vlayout->addWidget(m_tree);
+
+ QPushButton *pb = new QPushButton(tr("Refresh"), treeWid);
+ QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
+ vlayout->addWidget(pb);
+
+ QTabWidget *tabs = new QTabWidget(this);
+
+ m_text = new QPlainTextEdit(this);
+ m_text->setReadOnly(true);
+ tabs->addTab(m_text, tr("File"));
+
+ m_warnings = new QTreeWidget(this);
+ m_warnings->setHeaderHidden(true);
+ tabs->addTab(m_warnings, tr("Warnings"));
+
+ m_watches = new QmlWatches(this);
+ m_watchTable = new QTableView(this);
+ m_watchTable->setSelectionMode(QTableWidget::NoSelection);
+ m_watchTable->setModel(m_watches);
+ tabs->addTab(m_watchTable, tr("Watches"));
+
+ m_properties = new QmlPropertyView(m_watches, this);
+ QObject::connect(m_properties, SIGNAL(objectClicked(quint32)),
+ this, SLOT(highlightObject(quint32)));
+ tabs->addTab(m_properties, tr("Properties"));
+ tabs->setCurrentWidget(m_properties);
+
+ splitter->addWidget(tabs);
+ splitter->setStretchFactor(1, 2);
+
+ setGeometry(0, 100, 800, 600);
+}
+
+void QmlDebugger::itemDoubleClicked(QTreeWidgetItem *)
+{
+}
+
+void QmlDebugger::addWatch(QObject *obj, const QString &expr)
+{
+ QmlContext *ctxt = qmlContext(obj);
+ if(ctxt) {
+ QmlExpressionObject *e= new QmlExpressionObject(ctxt, expr, obj, m_watches);
+ m_watches->addWatch(e);
+ }
+}
+
+void QmlDebugger::highlightObject(quint32 id)
+{
+ QHash<quint32, QTreeWidgetItem *>::ConstIterator iter = m_items.find(id);
+ if (m_highlightedItem) {
+ m_highlightedItem->setBackground(0, QPalette().base());
+ m_highlightedItem = 0;
+ }
+
+ if (iter != m_items.end()) {
+ m_highlightedItem = *iter;
+ m_highlightedItem->setBackground(0, QColor("cyan"));
+ m_tree->expandItem(m_highlightedItem);
+ m_tree->scrollToItem(m_highlightedItem);
+ }
+}
+
+void QmlDebugger::itemClicked(QTreeWidgetItem *i)
+{
+ QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
+
+ if(m_selectedItem) {
+ QmlDebuggerStatus *debug =
+ qobject_cast<QmlDebuggerStatus *>(m_selectedItem);
+ Q_ASSERT(debug);
+ debug->setSelectedState(false);
+ m_selectedItem = 0;
+ }
+
+ if(item->object) {
+ QmlDebuggerStatus *debug =
+ qobject_cast<QmlDebuggerStatus *>(item->object);
+ if(debug) {
+ debug->setSelectedState(true);
+ m_selectedItem = item->object;
+ }
+
+ m_properties->setObject(item->object);
+ }
+
+ if(item->url.scheme() == QLatin1String("file")) {
+ QString f = item->url.toLocalFile();
+ QFile file(f);
+ file.open(QIODevice::ReadOnly);
+ QByteArray ba = file.readAll();
+ QTextStream stream(ba, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+
+ m_text->setPlainText(code);
+
+ if(item->startLine != -1) {
+ QTextDocument *document = m_text->document();
+ QTextCharFormat format;
+ format.setForeground(Qt::lightGray);
+
+ {
+ QTextCursor cursor(document);
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->endLine);
+ cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ cursor.setCharFormat(format);
+ }
+
+ {
+ QTextCursor cursor(document);
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, item->startLine - 1);
+ cursor.setCharFormat(format);
+ }
+
+ {
+ QTextCursor cursor(document);
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->startLine - 1);
+ m_text->setTextCursor(cursor);
+ m_text->centerCursor();
+ }
+
+
+ }
+
+ }
+}
+
+bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item)
+{
+ bool rv = true;
+
+ QString text;
+
+ item->object = obj;
+
+ if(QmlBindableValue *bv = qobject_cast<QmlBindableValue *>(obj)) {
+ QmlExpressionPrivate *p = bv->d;
+
+ text = bv->property().name() + QLatin1String(": ") + bv->expression();
+ item->setForeground(0, Qt::green);
+ item->bindableValue = bv;
+
+ if(p->log) {
+ QTreeWidgetItem *warningItem = 0;
+
+ for(int ii = 0; ii < p->log->count(); ++ii) {
+ const QmlExpressionLog &log = p->log->at(ii);
+
+ QString variant; QDebug d(&variant); d << log.result();
+
+ if(!log.warnings().isEmpty()) {
+
+ if(!warningItem) {
+ warningItem = new QTreeWidgetItem(m_warnings);
+ warningItem->setText(0, bv->expression());
+ }
+
+ QTreeWidgetItem *entry = new QTreeWidgetItem(warningItem);
+ entry->setExpanded(true);
+
+ entry->setText(0, variant);
+
+ foreach(const QString &warning, log.warnings()) {
+ QTreeWidgetItem *w = new QTreeWidgetItem(entry);
+ w->setText(0, warning);
+ }
+ }
+
+ }
+
+ }
+
+ delete item;
+ return false;
+
+ } else if(QmlBoundSignal *bs = qobject_cast<QmlBoundSignal *>(obj)) {
+ delete item;
+ return false;
+ } else {
+ QmlContext *context = qmlContext(obj);
+ QmlContext *parentContext = qmlContext(obj->parent());
+
+ text = QLatin1String(obj->metaObject()->className());
+
+ if(context && context != parentContext) {
+ QmlContextPrivate *p = static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+
+ QString toolTipString;
+ if(!p->url.toString().isEmpty()) {
+ item->url = p->url;
+ toolTipString = QLatin1String("URL: ") + p->url.toString();
+ }
+
+ if(!p->typeName.isEmpty()) {
+ if(!toolTipString.isEmpty())
+ toolTipString.prepend(QLatin1Char('\n'));
+ toolTipString.prepend(tr("Root type: ") + text);
+ text = QString::fromAscii(p->typeName);
+ }
+
+ if(!toolTipString.isEmpty())
+ item->setToolTip(0, toolTipString);
+
+ item->setForeground(0, QColor("orange"));
+
+ if(p->startLine != -1) {
+ item->startLine = p->startLine;
+ item->endLine = p->endLine;
+ }
+
+ } else {
+ item->setExpanded(true);
+ }
+
+ if(!context)
+ item->setForeground(0, Qt::lightGray);
+ }
+
+ m_items.insert(m_watches->objectId(obj), item);
+ item->setText(0, text);
+
+ return rv;
+}
+
+void QmlDebugger::buildTree(QObject *obj, QmlDebuggerItem *parent)
+{
+ QObjectList children = obj->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlDebuggerItem *item = new QmlDebuggerItem(parent);
+ if(makeItem(children.at(ii), item))
+ buildTree(children.at(ii), item);
+ }
+}
+
+void QmlDebugger::refresh()
+{
+ setDebugObject(m_object);
+}
+
+bool operator<(const QPair<quint32, QPair<int, QString> > &lhs,
+ const QPair<quint32, QPair<int, QString> > &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+void QmlDebugger::setCanvas(QSimpleCanvas *c)
+{
+ Q_UNUSED(c);
+}
+
+void QmlDebugger::setDebugObject(QObject *obj)
+{
+ m_tree->clear();
+ m_warnings->clear();
+ m_items.clear();
+ m_highlightedItem = 0;
+
+ m_object = obj;
+ if(!obj)
+ return;
+
+ QmlDebuggerItem *item = new QmlDebuggerItem(m_tree);
+ makeItem(obj, item);
+ buildTree(obj, item);
+ item->setExpanded(true);
+}
+
diff --git a/src/declarative/debugger/qmldebugger.h b/src/declarative/debugger/qmldebugger.h
new file mode 100644
index 0000000..10b2f9a
--- /dev/null
+++ b/src/declarative/debugger/qmldebugger.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGGER_H
+#define QMLDEBUGGER_H
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QTreeWidget;
+class QTreeWidgetItem;
+class QPlainTextEdit;
+class QmlDebuggerItem;
+class QTableView;
+class QmlPropertyView;
+class QmlWatches;
+class QmlObjectTree;
+class QmlContext;
+class QSimpleCanvas;
+class QmlDebugger : public QWidget
+{
+Q_OBJECT
+public:
+ QmlDebugger(QWidget *parent = 0);
+
+ void setDebugObject(QObject *);
+ void setCanvas(QSimpleCanvas *);
+
+public slots:
+ void refresh();
+
+private slots:
+ void itemClicked(QTreeWidgetItem *);
+ void itemDoubleClicked(QTreeWidgetItem *);
+ void highlightObject(quint32);
+ void addWatch(QObject *, const QString &);
+
+private:
+ void buildTree(QObject *obj, QmlDebuggerItem *parent);
+ bool makeItem(QObject *obj, QmlDebuggerItem *item);
+ QmlObjectTree *m_tree;
+ QTreeWidget *m_warnings;
+ QTableView *m_watchTable;
+ QmlWatches *m_watches;
+ QmlPropertyView *m_properties;
+ QPlainTextEdit *m_text;
+ QPointer<QObject> m_object;
+ QPointer<QObject> m_selectedItem;
+
+ QTreeWidgetItem *m_highlightedItem;
+ QHash<quint32, QTreeWidgetItem *> m_items;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDEBUGGER_H
+
diff --git a/src/declarative/debugger/qmldebuggerstatus.cpp b/src/declarative/debugger/qmldebuggerstatus.cpp
new file mode 100644
index 0000000..d46a21d
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebuggerstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlDebuggerStatus::~QmlDebuggerStatus()
+{
+}
+
+void QmlDebuggerStatus::setSelectedState(bool)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebuggerstatus.h b/src/declarative/debugger/qmldebuggerstatus.h
new file mode 100644
index 0000000..62336de
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGGERSTATUS_P_H
+#define QMLDEBUGGERSTATUS_P_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlDebuggerStatus
+{
+public:
+ virtual ~QmlDebuggerStatus();
+
+ virtual void setSelectedState(bool);
+};
+Q_DECLARE_INTERFACE(QmlDebuggerStatus, "com.trolltech.qml.QmlDebuggerStatus")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLMDEBUGGERSTATUS_P_H
+
diff --git a/src/declarative/debugger/qmldebugserver.cpp b/src/declarative/debugger/qmldebugserver.cpp
new file mode 100644
index 0000000..23e59e0
--- /dev/null
+++ b/src/declarative/debugger/qmldebugserver.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebugserver.h"
+#include <QtCore/qdebug.h>
+#include <QtNetwork/qtcpserver.h>
+#include <QtNetwork/qtcpsocket.h>
+#include <private/qobject_p.h>
+#include <QtDeclarative/qpacketprotocol.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlDebugServerPrivate;
+class QmlDebugServer : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlDebugServer)
+ Q_DISABLE_COPY(QmlDebugServer)
+public:
+ static QmlDebugServer *instance();
+
+private slots:
+ void readyRead();
+
+private:
+ friend class QmlDebugServerPlugin;
+ friend class QmlDebugServerPluginPrivate;
+ QmlDebugServer(int);
+};
+
+class QmlDebugServerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDebugServer)
+public:
+ QmlDebugServerPrivate();
+ void init(int port);
+
+ QTcpSocket *connection;
+ QPacketProtocol *protocol;
+ QHash<QString, QmlDebugServerPlugin *> plugins;
+ QStringList enabledPlugins;
+};
+
+class QmlDebugServerPluginPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDebugServerPlugin)
+public:
+ QmlDebugServerPluginPrivate();
+
+ QString name;
+ QmlDebugServer *server;
+};
+
+QmlDebugServerPrivate::QmlDebugServerPrivate()
+: connection(0), protocol(0)
+{
+}
+
+void QmlDebugServerPrivate::init(int port)
+{
+ Q_Q(QmlDebugServer);
+ QTcpServer server;
+
+ if (!server.listen(QHostAddress::Any, port)) {
+ qWarning("QmlDebugServer: Unable to listen on port %d", port);
+ return;
+ }
+
+ qWarning("QmlDebugServer: Waiting for connection on port %d...", port);
+
+ if (!server.waitForNewConnection(-1)) {
+ qWarning("QmlDebugServer: Connection error");
+ return;
+ }
+
+ connection = server.nextPendingConnection();
+ connection->setParent(q);
+ protocol = new QPacketProtocol(connection, q);
+
+ // ### Wait for hello
+ while (!protocol->packetsAvailable()) {
+ connection->waitForReadyRead();
+ }
+ QPacket hello = protocol->read();
+ QString name;
+ hello >> name >> enabledPlugins;
+ if (name != QLatin1String("QmlDebugServer")) {
+ qWarning("QmlDebugServer: Invalid hello message");
+ delete protocol; delete connection; connection = 0; protocol = 0;
+ return;
+ }
+
+ QObject::connect(protocol, SIGNAL(readyRead()), q, SLOT(readyRead()));
+ q->readyRead();
+
+ qWarning("QmlDebugServer: Connection established");
+}
+
+QmlDebugServer *QmlDebugServer::instance()
+{
+ static bool envTested = false;
+ static QmlDebugServer *server = 0;
+
+ if (!envTested) {
+ envTested = true;
+ QByteArray env = qgetenv("QML_DEBUG_SERVER_PORT");
+
+ bool ok = false;
+ int port = env.toInt(&ok);
+
+ if (ok && port > 1024)
+ server = new QmlDebugServer(port);
+ }
+
+ if (server && server->d_func()->connection)
+ return server;
+ else
+ return 0;
+}
+
+QmlDebugServer::QmlDebugServer(int port)
+: QObject(*(new QmlDebugServerPrivate))
+{
+ Q_D(QmlDebugServer);
+ d->init(port);
+}
+
+void QmlDebugServer::readyRead()
+{
+ Q_D(QmlDebugServer);
+
+ QString debugServer(QLatin1String("QmlDebugServer"));
+
+ while (d->protocol->packetsAvailable()) {
+ QPacket pack = d->protocol->read();
+
+ QString name;
+ pack >> name;
+
+ if (name == debugServer) {
+ int op = -1; QString plugin;
+ pack >> op >> plugin;
+
+ if (op == 1) {
+ // Enable
+ if (!d->enabledPlugins.contains(plugin)) {
+ d->enabledPlugins.append(plugin);
+ QHash<QString, QmlDebugServerPlugin *>::Iterator iter =
+ d->plugins.find(plugin);
+ if (iter != d->plugins.end())
+ (*iter)->enabledChanged(true);
+ }
+
+ } else if (op == 2) {
+ // Disable
+ if (d->enabledPlugins.contains(plugin)) {
+ d->enabledPlugins.removeAll(plugin);
+ QHash<QString, QmlDebugServerPlugin *>::Iterator iter =
+ d->plugins.find(plugin);
+ if (iter != d->plugins.end())
+ (*iter)->enabledChanged(false);
+ }
+ } else {
+ qWarning("QmlDebugServer: Invalid control message %d", op);
+ }
+
+ } else {
+ QByteArray message;
+ pack >> message;
+
+ QHash<QString, QmlDebugServerPlugin *>::Iterator iter =
+ d->plugins.find(name);
+ if (iter == d->plugins.end()) {
+ qWarning() << "QmlDebugServer: Message received for missing plugin" << name;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+ }
+ }
+}
+
+QmlDebugServerPluginPrivate::QmlDebugServerPluginPrivate()
+: server(0)
+{
+}
+
+QmlDebugServerPlugin::QmlDebugServerPlugin(const QString &name, QObject *parent)
+: QObject(*(new QmlDebugServerPluginPrivate), parent)
+{
+ Q_D(QmlDebugServerPlugin);
+ d->name = name;
+ d->server = QmlDebugServer::instance();
+
+ if (!d->server)
+ return;
+
+ if (d->server->d_func()->plugins.contains(name)) {
+ qWarning() << "QmlDebugServerPlugin: Conflicting plugin name" << name;
+ d->server = 0;
+ } else {
+ d->server->d_func()->plugins.insert(name, this);
+ }
+}
+
+QString QmlDebugServerPlugin::name() const
+{
+ Q_D(const QmlDebugServerPlugin);
+ return d->name;
+}
+
+bool QmlDebugServerPlugin::isEnabled() const
+{
+ Q_D(const QmlDebugServerPlugin);
+ return (d->server && d->server->d_func()->enabledPlugins.contains(d->name));
+}
+
+bool QmlDebugServerPlugin::isDebuggingEnabled()
+{
+ return QmlDebugServer::instance() != 0;
+}
+
+QString QmlDebugServerPlugin::objectToString(QObject *obj)
+{
+ if(!obj)
+ return QLatin1String("NULL");
+
+ QString objectName = obj->objectName();
+ if(objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+
+ QString rv = QLatin1String(obj->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+
+ return rv;
+}
+
+void QmlDebugServerPlugin::sendMessage(const QByteArray &message)
+{
+ Q_D(QmlDebugServerPlugin);
+
+ if (!d->server || !d->server->d_func()->connection)
+ return;
+
+ QPacket pack;
+ pack << d->name << message;
+ d->server->d_func()->protocol->send(pack);
+ d->server->d_func()->connection->flush();
+}
+
+void QmlDebugServerPlugin::enabledChanged(bool)
+{
+}
+
+void QmlDebugServerPlugin::messageReceived(const QByteArray &)
+{
+}
+
+#include "qmldebugserver.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebugserver.h b/src/declarative/debugger/qmldebugserver.h
new file mode 100644
index 0000000..02fe7d1
--- /dev/null
+++ b/src/declarative/debugger/qmldebugserver.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGSERVER_H
+#define QMLDEBUGSERVER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QmlDebugServerPluginPrivate;
+class QmlDebugServerPlugin : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlDebugServerPlugin)
+ Q_DISABLE_COPY(QmlDebugServerPlugin)
+public:
+ QmlDebugServerPlugin(const QString &, QObject *parent = 0);
+
+ QString name() const;
+
+ bool isEnabled() const;
+
+ void sendMessage(const QByteArray &);
+
+ static bool isDebuggingEnabled();
+ static QString objectToString(QObject *obj);
+
+protected:
+ virtual void enabledChanged(bool);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ friend class QmlDebugServer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDEBUGSERVER_H
+
diff --git a/src/declarative/debugger/qmlobjecttree.cpp b/src/declarative/debugger/qmlobjecttree.cpp
new file mode 100644
index 0000000..27dc000
--- /dev/null
+++ b/src/declarative/debugger/qmlobjecttree.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qmlobjecttree_p.h>
+#include <QtDeclarative/qml.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qmenu.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qaction.h>
+#include <QtGui/qinputdialog.h>
+#include <QtGui/qboxlayout.h>
+
+QmlObjectTree::QmlObjectTree(QWidget *parent)
+: QTreeWidget(parent)
+{
+}
+
+void QmlObjectTree::mousePressEvent(QMouseEvent *me)
+{
+ QTreeWidget::mousePressEvent(me);
+ if(me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) {
+ QAction action(tr("Add watch..."), 0);
+ QList<QAction *> actions;
+ actions << &action;
+ QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(currentItem());
+ if(item && qmlContext(item->object) &&
+ QMenu::exec(actions, me->globalPos())) {
+
+ bool ok = false;
+ QString watch = QInputDialog::getText(this, tr("Watch expression"), tr("Expression:"), QLineEdit::Normal, QString(), &ok);
+
+ if(ok && !watch.isEmpty())
+ emit addWatch(item->object, watch);
+ }
+ }
+}
+
diff --git a/src/declarative/debugger/qmlobjecttree_p.h b/src/declarative/debugger/qmlobjecttree_p.h
new file mode 100644
index 0000000..4e6d484
--- /dev/null
+++ b/src/declarative/debugger/qmlobjecttree_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOBJECTTREE_P_H
+#define QMLOBJECTTREE_P_H
+
+#include <QtGui/qtreewidget.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qpointer.h>
+
+class QmlBindableValue;
+class QmlDebuggerItem : public QTreeWidgetItem
+{
+public:
+ QmlDebuggerItem(QTreeWidget *wid)
+ : QTreeWidgetItem(wid), startLine(-1), endLine(-1)
+ {
+ }
+
+ QmlDebuggerItem(QTreeWidgetItem *item)
+ : QTreeWidgetItem(item), startLine(-1), endLine(-1)
+ {
+ }
+
+ int startLine;
+ int endLine;
+ QUrl url;
+
+ QPointer<QObject> object;
+ QPointer<QmlBindableValue> bindableValue;
+};
+
+class QmlContext;
+class QmlObjectTree : public QTreeWidget
+{
+ Q_OBJECT
+public:
+ QmlObjectTree(QWidget *parent = 0);
+
+signals:
+ void addWatch(QObject *, const QString &);
+
+protected:
+ virtual void mousePressEvent(QMouseEvent *);
+};
+
+#endif // QMLOBJECTTREE_P_H
+
diff --git a/src/declarative/debugger/qmlpropertyview.cpp b/src/declarative/debugger/qmlpropertyview.cpp
new file mode 100644
index 0000000..abe1902
--- /dev/null
+++ b/src/declarative/debugger/qmlpropertyview.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertyview_p.h"
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qtreewidget.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlbindablevalue.h>
+#include <private/qmlboundsignal_p.h>
+
+QmlPropertyView::QmlPropertyView(QmlWatches *watches, QWidget *parent)
+: QWidget(parent), m_tree(0), m_watches(watches)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ setLayout(layout);
+
+ m_tree = new QTreeWidget(this);
+ m_tree->setHeaderLabels(QStringList() << tr("Property") << tr("Value"));
+ QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+ this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
+ this, SLOT(itemClicked(QTreeWidgetItem *)));
+
+ m_tree->setColumnCount(2);
+
+ layout->addWidget(m_tree);
+}
+
+class QmlPropertyViewItem : public QObject, public QTreeWidgetItem
+{
+Q_OBJECT
+public:
+ QmlPropertyViewItem(QTreeWidget *widget);
+ QmlPropertyViewItem(QTreeWidgetItem *parent);
+
+ QObject *object;
+ QMetaProperty property;
+
+ quint32 exprId;
+
+public slots:
+ void refresh();
+};
+
+QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidget *widget)
+: QTreeWidgetItem(widget), object(0), exprId(0)
+{
+}
+
+QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidgetItem *parent)
+: QTreeWidgetItem(parent), object(0), exprId(0)
+{
+}
+
+void QmlPropertyViewItem::refresh()
+{
+ QVariant v = property.read(object);
+ QString str = v.toString();
+
+ if (QmlMetaType::isObject(v.userType()))
+ str = QmlWatches::objectToString(QmlMetaType::toQObject(v));
+
+ setText(1, str);
+}
+
+void QmlPropertyView::itemClicked(QTreeWidgetItem *i)
+{
+ QmlPropertyViewItem *item = static_cast<QmlPropertyViewItem *>(i);
+
+ if(item->object) {
+ QVariant v = item->property.read(item->object);
+ if (QmlMetaType::isObject(v.userType())) {
+ QObject *obj = QmlMetaType::toQObject(v);
+
+ if(obj) {
+ quint32 id = m_watches->objectId(obj);
+ emit objectClicked(id);
+ }
+ }
+ }
+
+}
+
+void QmlPropertyView::itemDoubleClicked(QTreeWidgetItem *i)
+{
+ QmlPropertyViewItem *item = static_cast<QmlPropertyViewItem *>(i);
+
+ if(item->object) {
+ quint32 objectId = m_watches->objectId(item->object);
+
+ if(m_watches->hasWatch(objectId, item->property.name())) {
+ m_watches->remWatch(objectId, item->property.name());
+ item->setForeground(0, Qt::black);
+ } else {
+ m_watches->addWatch(objectId, item->property.name());
+ item->setForeground(0, Qt::red);
+ }
+ }
+
+}
+
+void QmlPropertyView::setObject(QObject *object)
+{
+ m_object = object;
+
+ m_tree->clear();
+ if(!m_object)
+ return;
+
+ QMultiHash<QByteArray, QPair<QString, quint32> > bindings;
+ QHash<QByteArray, QString> sigs;
+ QObjectList children = object->children();
+
+ foreach(QObject *child, children) {
+ if(QmlBindableValue *value = qobject_cast<QmlBindableValue *>(child)) {
+ bindings.insert(value->property().name().toUtf8(), qMakePair(value->expression(), value->id()));
+ } else if(QmlBoundSignal *signal = qobject_cast<QmlBoundSignal *>(child)) {
+ QMetaMethod method = object->metaObject()->method(signal->index());
+ QByteArray sig = method.signature();
+ sigs.insert(sig, signal->expression());
+ }
+ }
+
+ quint32 objectId = m_watches->objectId(object);
+
+ const QMetaObject *mo = object->metaObject();
+ for(int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QMetaProperty p = mo->property(ii);
+
+ if(QmlMetaType::isList(p.userType()) ||
+ QmlMetaType::isQmlList(p.userType()))
+ continue;
+
+ QmlPropertyViewItem *item = new QmlPropertyViewItem(m_tree);
+
+ item->object = object;
+ item->property = p;
+
+ item->setText(0, QLatin1String(p.name()));
+ if(m_watches->hasWatch(objectId, p.name()))
+ item->setForeground(0, Qt::red);
+
+ static int refreshIdx = -1;
+ if(refreshIdx == -1)
+ refreshIdx = QmlPropertyViewItem::staticMetaObject.indexOfMethod("refresh()");
+
+ if(p.hasNotifySignal())
+ QMetaObject::connect(object, p.notifySignalIndex(),
+ item, refreshIdx);
+
+
+ QMultiHash<QByteArray, QPair<QString, quint32> >::Iterator iter =
+ bindings.find(p.name());
+
+ while(iter != bindings.end() && iter.key() == p.name()) {
+ QmlPropertyViewItem *binding = new QmlPropertyViewItem(item);
+ binding->exprId = iter.value().second;
+ binding->setText(1, iter.value().first);
+ binding->setForeground(1, Qt::green);
+ ++iter;
+ }
+
+ item->setExpanded(true);
+ item->refresh();
+ }
+
+ for(QHash<QByteArray, QString>::ConstIterator iter = sigs.begin();
+ iter != sigs.end();
+ ++iter) {
+
+ QTreeWidgetItem *item = new QTreeWidgetItem(m_tree);
+ item->setText(0, QString::fromAscii(iter.key()));
+ item->setForeground(0, Qt::blue);
+ item->setText(1, iter.value());
+ }
+}
+
+void QmlPropertyView::refresh()
+{
+ setObject(m_object);
+}
+
+#include "qmlpropertyview.moc"
diff --git a/src/declarative/debugger/qmlpropertyview_p.h b/src/declarative/debugger/qmlpropertyview_p.h
new file mode 100644
index 0000000..469a08d
--- /dev/null
+++ b/src/declarative/debugger/qmlpropertyview_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVIEW_P_H
+#define QMLPROPERTYVIEW_P_H
+
+#include <QtGui/qwidget.h>
+#include <QtCore/qpointer.h>
+#include <private/qmlwatches_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTreeWidget;
+class QTreeWidgetItem;
+class QmlPropertyView : public QWidget
+{
+ Q_OBJECT
+public:
+ QmlPropertyView(QmlWatches *watches, QWidget *parent = 0);
+
+ void setObject(QObject *);
+
+signals:
+ void objectClicked(quint32);
+
+public slots:
+ void refresh();
+ void itemDoubleClicked(QTreeWidgetItem *);
+ void itemClicked(QTreeWidgetItem *);
+
+private:
+ QPointer<QObject> m_object;
+ QTreeWidget *m_tree;
+ QmlWatches *m_watches;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLPROPERTYVIEW_P_H
+
diff --git a/src/declarative/debugger/qmlwatches.cpp b/src/declarative/debugger/qmlwatches.cpp
new file mode 100644
index 0000000..bac4cbd
--- /dev/null
+++ b/src/declarative/debugger/qmlwatches.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlwatches_p.h"
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qcolor.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlexpression.h>
+
+QString QmlWatches::objectToString(QObject *obj)
+{
+ if(!obj)
+ return QLatin1String("NULL");
+
+ QString objectName = obj->objectName();
+ if(objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+
+ QString rv = QLatin1String(obj->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+
+ return rv;
+}
+
+class QmlWatchesProxy : public QObject
+{
+ Q_OBJECT
+public:
+ QmlWatchesProxy(QObject *object,
+ const QMetaProperty &prop,
+ int column,
+ QmlWatches *parent = 0);
+
+ QmlWatchesProxy(QmlExpressionObject *object,
+ int column,
+ QmlWatches *parent = 0);
+
+public slots:
+ void refresh();
+
+private:
+ QmlWatches *m_watches;
+ QObject *m_object;
+ QMetaProperty m_property;
+
+ QmlExpressionObject *m_expr;
+ int m_column;
+};
+
+QmlWatchesProxy::QmlWatchesProxy(QmlExpressionObject *object,
+ int column,
+ QmlWatches *parent)
+: QObject(parent), m_watches(parent), m_object(0), m_expr(object), m_column(column)
+{
+ QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(refresh()));
+}
+
+QmlWatchesProxy::QmlWatchesProxy(QObject *object,
+ const QMetaProperty &prop,
+ int column,
+ QmlWatches *parent)
+: QObject(parent), m_watches(parent), m_object(object), m_property(prop),
+ m_expr(0), m_column(column)
+{
+ static int refreshIdx = -1;
+ if(refreshIdx == -1)
+ refreshIdx = QmlWatchesProxy::staticMetaObject.indexOfMethod("refresh()");
+
+ QMetaObject::connect(m_object, prop.notifySignalIndex(),
+ this, refreshIdx);
+}
+
+void QmlWatchesProxy::refresh()
+{
+ QVariant v;
+ if(m_expr) v = m_expr->value();
+ else v= m_property.read(m_object);
+
+ m_watches->addValue(m_column, v);
+}
+
+QmlWatches::QmlWatches(QObject *parent)
+: QAbstractTableModel(parent), m_uniqueId(0)
+{
+}
+
+bool QmlWatches::hasWatch(quint32 objectId, const QByteArray &property)
+{
+ return m_watches.contains(qMakePair(objectId, property));
+}
+
+void QmlWatches::addWatch(QmlExpressionObject *expr)
+{
+ int oldColumn = columnCount(QModelIndex());
+
+ m_watches.append(qMakePair(quint32(0), QByteArray()));
+
+ beginInsertColumns(QModelIndex(), oldColumn, oldColumn);
+ endInsertColumns();
+
+ m_columnNames.append(expr->expression());
+
+ QmlWatchesProxy *proxy = new QmlWatchesProxy(expr, oldColumn, this);
+ m_proxies.append(proxy);
+
+ proxy->refresh();
+ m_values[m_values.count() - 1].first = true;
+}
+
+void QmlWatches::addWatch(quint32 objectId, const QByteArray &property)
+{
+ if(hasWatch(objectId, property))
+ return;
+
+ int oldColumn = columnCount(QModelIndex());
+
+ m_watches.append(qMakePair(objectId, property));
+
+ beginInsertColumns(QModelIndex(), oldColumn, oldColumn);
+ endInsertColumns();
+
+ QObject *obj = object(objectId);
+ m_columnNames.append(QLatin1String(property) + QLatin1String(" on ") + objectToString(obj));
+ QMetaProperty prop =
+ obj->metaObject()->property(obj->metaObject()->indexOfProperty(property.constData()));
+ QmlWatchesProxy *proxy = new QmlWatchesProxy(obj, prop, oldColumn, this);
+ m_proxies.append(proxy);
+ proxy->refresh();
+ m_values[m_values.count() - 1].first = true;
+}
+
+void QmlWatches::remWatch(quint32 objectId, const QByteArray &property)
+{
+ QPair<quint32, QByteArray> watch = qMakePair(objectId, property);
+ for(int ii = 0; ii < m_watches.count(); ++ii) {
+ if(m_watches.at(ii) == watch) {
+ m_watches.removeAt(ii);
+ m_columnNames.removeAt(ii);
+ if(m_proxies.at(ii))
+ delete m_proxies.at(ii);
+ m_proxies.removeAt(ii);
+
+
+ for(QList<Value>::Iterator iter = m_values.begin();
+ iter != m_values.end();
+ ) {
+ if(iter->column == ii) {
+ iter = m_values.erase(iter);
+ } else {
+ if(iter->column > ii)
+ --iter->column;
+ ++iter;
+ }
+ }
+ reset();
+ return;
+ }
+ }
+}
+
+quint32 QmlWatches::objectId(QObject *object)
+{
+ Q_ASSERT(object);
+
+ QHash<QObject *, QPair<QPointer<QObject>, quint32> *>::Iterator iter =
+ m_objects.find(object);
+ if(iter == m_objects.end()) {
+ iter = m_objects.insert(object, new QPair<QPointer<QObject>, quint32>(QPointer<QObject>(object), m_uniqueId++));
+ m_objectIds.insert(iter.value()->second, iter.value());
+ }
+
+ if(iter.value()->first != object) {
+ iter.value()->first = object;
+ iter.value()->second = m_uniqueId++;
+
+ m_objectIds.insert(iter.value()->second, iter.value());
+ }
+ return iter.value()->second;
+}
+
+QObject *QmlWatches::object(quint32 id)
+{
+ QHash<quint32, QPair<QPointer<QObject>, quint32> *>::Iterator iter =
+ m_objectIds.find(id);
+ if(iter == m_objectIds.end())
+ return 0;
+
+ if(!iter.value()->first) {
+ m_objectIds.erase(iter);
+ return 0;
+ }
+
+ return iter.value()->first;
+}
+
+void QmlWatches::addValue(int column, const QVariant &value)
+{
+ int row = m_values.count();
+
+ beginInsertRows(QModelIndex(), row, row);
+ Value v;
+ v.column = column;
+ v.variant = value;
+ v.first = false;
+ m_values.append(v);
+ endInsertRows();
+}
+
+int QmlWatches::columnCount(const QModelIndex &) const
+{
+ return m_watches.count();
+}
+
+int QmlWatches::rowCount(const QModelIndex &) const
+{
+ return m_values.count();
+}
+
+QVariant QmlWatches::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && section < m_columnNames.count() &&
+ role == Qt::DisplayRole)
+ return m_columnNames.at(section);
+ else
+ return QVariant();
+}
+
+QVariant QmlWatches::data(const QModelIndex &idx, int role) const
+{
+ if(m_values.at(idx.row()).column == idx.column()) {
+ if(role == Qt::DisplayRole) {
+ const QVariant &value = m_values.at(idx.row()).variant;
+
+ QString str = value.toString();
+
+ if(str.isEmpty() && QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ if(o) {
+ QString objectName = o->objectName();
+ if(objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+ str = QLatin1String(o->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+ }
+ }
+
+ if(str.isEmpty()) {
+ QDebug d(&str);
+ d << value;
+ }
+ return QVariant(str);
+ } else if(role == Qt::BackgroundRole) {
+ if(m_values.at(idx.row()).first)
+ return QColor(Qt::green);
+ else
+ return QVariant();
+ } else {
+ return QVariant();
+ }
+ } else {
+ return QVariant();
+ }
+}
+
+#include "qmlwatches.moc"
diff --git a/src/declarative/debugger/qmlwatches_p.h b/src/declarative/debugger/qmlwatches_p.h
new file mode 100644
index 0000000..6c383a1
--- /dev/null
+++ b/src/declarative/debugger/qmlwatches_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLWATCHES_P_H
+#define QMLWATCHES_P_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qabstractitemmodel.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlWatchesProxy;
+class QmlExpressionObject;
+
+class QmlWatches : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ QmlWatches(QObject *parent = 0);
+
+ bool hasWatch(quint32 objectId, const QByteArray &property);
+ void addWatch(quint32 objectId, const QByteArray &property);
+ void remWatch(quint32 objectId, const QByteArray &property);
+
+ void addWatch(QmlExpressionObject *);
+
+ quint32 objectId(QObject *);
+ QObject *object(quint32);
+
+ static QString objectToString(QObject *obj);
+protected:
+ int columnCount(const QModelIndex &) const;
+ int rowCount(const QModelIndex &) const;
+ QVariant data(const QModelIndex &, int) const;
+ QVariant headerData(int, Qt::Orientation, int) const;
+
+private:
+ friend class QmlWatchesProxy;
+ QList<QPair<quint32, QByteArray> > m_watches;
+
+ void addValue(int, const QVariant &);
+ struct Value {
+ int column;
+ QVariant variant;
+ bool first;
+ };
+ QList<Value> m_values;
+ QStringList m_columnNames;
+ QList<QPointer<QmlWatchesProxy> > m_proxies;
+
+ quint32 m_uniqueId;
+ QHash<QObject *, QPair<QPointer<QObject>, quint32> *> m_objects;
+ QHash<quint32, QPair<QPointer<QObject>, quint32> *> m_objectIds;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLWATCHES_P_H
diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp
new file mode 100644
index 0000000..6911b89
--- /dev/null
+++ b/src/declarative/debugger/qpacketprotocol.cpp
@@ -0,0 +1,462 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qpacketprotocol.h"
+#include <QBuffer>
+
+#define MAX_PACKET_SIZE 0x7FFFFFFF
+
+/*!
+ \class QPacketProtocol
+
+ \brief The QPacketProtocol class encapsulates communicating discrete packets
+ across fragmented IO channels, such as TCP sockets.
+
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ fragmented transports such as TCP and UDP.
+
+ As transmission boundaries are not respected, sending packets over protocols
+ like TCP frequently involves "stitching" them back together at the receiver.
+ QPacketProtocol makes this easier by performing this task for you. Packet
+ data sent using QPacketProtocol is prepended with a 4-byte size header
+ allowing the receiving QPacketProtocol to buffer the packet internally until
+ it has all been received. QPacketProtocol does not perform any sanity
+ checking on the size or on the data, so this class should only be used in
+ prototyping or trusted situations where DOS attacks are unlikely.
+
+ QPacketProtocol does not perform any communications itself. Instead it can
+ operate on any QIODevice that supports the QIODevice::readyRead() signal. A
+ logical "packet" is encapsulated by the companion QPacket class. The
+ following example shows two ways to send data using QPacketProtocol. The
+ transmitted data is equivalent in both.
+
+ \code
+ QTcpSocket socket;
+ // ... connect socket ...
+
+ QPacketProtocol protocol(&socket);
+
+ // Send packet the quick way
+ protocol.send() << "Hello world" << 123;
+
+ // Send packet the longer way
+ QPacket packet;
+ packet << "Hello world" << 123;
+ protocol.send(packet);
+ \endcode
+
+ Likewise, the following shows how to read data from QPacketProtocol, assuming
+ that the QPacketProtocol::readyRead() signal has been emitted.
+
+ \code
+ // ... QPacketProtocol::readyRead() is emitted ...
+
+ int a;
+ QByteArray b;
+
+ // Receive packet the quick way
+ protocol.read() >> a >> b;
+
+ // Receive packet the longer way
+ QPacket packet = protocol.read();
+ p >> a >> b;
+ \endcode
+
+ \ingroup io
+ \sa QPacket
+*/
+
+class QPacketProtocolPrivate : public QObject
+{
+Q_OBJECT
+public:
+ QPacketProtocolPrivate(QPacketProtocol * parent, QIODevice * _dev)
+ : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
+ dev(_dev)
+ {
+ Q_ASSERT(4 == sizeof(qint32));
+
+ QObject::connect(this, SIGNAL(readyRead()),
+ parent, SIGNAL(readyRead()));
+ QObject::connect(this, SIGNAL(packetWritten()),
+ parent, SIGNAL(packetWritten()));
+ QObject::connect(this, SIGNAL(invalidPacket()),
+ parent, SIGNAL(invalidPacket()));
+ QObject::connect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::connect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ }
+
+signals:
+ void readyRead();
+ void packetWritten();
+ void invalidPacket();
+
+public slots:
+ void aboutToClose()
+ {
+ inProgress.clear();
+ sendingPackets.clear();
+ inProgressSize = -1;
+ }
+
+ void bytesWritten(qint64 bytes)
+ {
+ Q_ASSERT(!sendingPackets.isEmpty());
+
+ while(bytes) {
+ if(sendingPackets.at(0) > bytes) {
+ sendingPackets[0] -= bytes;
+ bytes = 0;
+ } else {
+ bytes -= sendingPackets.at(0);
+ sendingPackets.removeFirst();
+ emit packetWritten();
+ }
+ }
+ }
+
+ void readyToRead()
+ {
+ if(-1 == inProgressSize) {
+ // We need a size header of sizeof(qint32)
+ if(sizeof(qint32) > dev->bytesAvailable())
+ return;
+
+ // Read size header
+ int read = dev->read((char *)&inProgressSize, sizeof(qint32));
+ Q_ASSERT(read == sizeof(qint32));
+ Q_UNUSED(read);
+
+ // Check sizing constraints
+ if(inProgressSize > maxPacketSize) {
+ QObject::disconnect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::disconnect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ dev = 0;
+ emit invalidPacket();
+ return;
+ }
+
+ inProgressSize -= sizeof(qint32);
+
+ // Need to get trailing data
+ readyToRead();
+ } else {
+ inProgress.append(dev->read(inProgressSize - inProgress.size()));
+
+ if(inProgressSize == inProgress.size()) {
+ // Packet has arrived!
+ packets.append(inProgress);
+ inProgressSize = -1;
+ inProgress.clear();
+
+ emit readyRead();
+
+ // Need to get trailing data
+ readyToRead();
+ }
+ }
+ }
+
+public:
+ QList<qint64> sendingPackets;
+ QList<QByteArray> packets;
+ QByteArray inProgress;
+ qint32 inProgressSize;
+ qint32 maxPacketSize;
+ QIODevice * dev;
+};
+
+/*!
+ Construct a QPacketProtocol instance that works on \a dev with the
+ specified \a parent.
+ */
+QPacketProtocol::QPacketProtocol(QIODevice * dev, QObject * parent)
+: QObject(parent), d(new QPacketProtocolPrivate(this, dev))
+{
+ Q_ASSERT(dev);
+}
+
+/*!
+ Destroys the QPacketProtocol instance.
+ */
+QPacketProtocol::~QPacketProtocol()
+{
+}
+
+/*!
+ Returns the maximum packet size allowed. By default this is
+ 2,147,483,647 bytes.
+
+ If a packet claiming to be larger than the maximum packet size is received,
+ the QPacketProtocol::invalidPacket() signal is emitted.
+
+ \sa QPacketProtocol::setMaximumPacketSize()
+ */
+qint32 QPacketProtocol::maximumPacketSize() const
+{
+ return d->maxPacketSize;
+}
+
+/*!
+ Sets the maximum allowable packet size to \a max.
+
+ \sa QPacketProtocol::maximumPacketSize()
+ */
+qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
+{
+ if(max > (signed)sizeof(qint32))
+ d->maxPacketSize = max;
+ return d->maxPacketSize;
+}
+
+/*!
+ Returns a streamable object that is transmitted on destruction. For example
+
+ \code
+ protocol.send() << "Hello world" << 123;
+ \endcode
+
+ will send a packet containing "Hello world" and 123. To construct more
+ complex packets, explicitly construct a QPacket instance.
+ */
+QPacketAutoSend QPacketProtocol::send()
+{
+ return QPacketAutoSend(this);
+}
+
+/*!
+ \fn void QPacketProtocol::send(const QPacket & packet)
+
+ Transmit the \a packet.
+ */
+void QPacketProtocol::send(const QPacket & p)
+{
+ if(p.b.isEmpty())
+ return; // We don't send empty packets
+
+ qint64 sendSize = p.b.size() + sizeof(qint32);
+
+ d->sendingPackets.append(sendSize);
+ qint32 sendSize32 = sendSize;
+ qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_ASSERT(writeBytes == sizeof(qint32));
+ writeBytes = d->dev->write(p.b);
+ Q_ASSERT(writeBytes == p.b.size());
+}
+
+/*!
+ Returns the number of received packets yet to be read.
+ */
+qint64 QPacketProtocol::packetsAvailable() const
+{
+ return d->packets.count();
+}
+
+/*!
+ Discard any unread packets.
+ */
+void QPacketProtocol::clear()
+{
+ d->packets.clear();
+}
+
+/*!
+ Return the next unread packet, or an invalid QPacket instance if no packets
+ are available. This method does NOT block.
+ */
+QPacket QPacketProtocol::read()
+{
+ if(0 == d->packets.count())
+ return QPacket();
+
+ QPacket rv(d->packets.at(0));
+ d->packets.removeFirst();
+ return rv;
+}
+
+/*!
+ Return the QIODevice passed to the QPacketProtocol constructor.
+*/
+QIODevice * QPacketProtocol::device()
+{
+ return d->dev;
+}
+
+/*!
+ \fn void QPacketProtocol::readyRead()
+
+ Emitted whenever a new packet is received. Applications may use
+ QPacketProtocol::read() to retrieve this packet.
+ */
+
+/*!
+ \fn void QPacketProtocol::invalidPacket()
+
+ A packet larger than the maximum allowable packet size was received. The
+ packet will be discarded and, as it indicates corruption in the protocol, no
+ further packets will be received.
+ */
+
+/*!
+ \fn void QPacketProtocol::packetWritten()
+
+ Emitted each time a packet is completing written to the device. This signal
+ may be used for communications flow control.
+ */
+
+/*!
+ \class QPacket
+ \inpublicgroup QtBaseModule
+
+ \brief The QPacket class encapsulates an unfragmentable packet of data to be
+ transmitted by QPacketProtocol.
+
+ The QPacket class works together with QPacketProtocol to make it simple to
+ send arbitrary sized data "packets" across fragmented transports such as TCP
+ and UDP.
+
+ QPacket provides a QDataStream interface to an unfragmentable packet.
+ Applications should construct a QPacket, propagate it with data and then
+ transmit it over a QPacketProtocol instance. For example:
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket myPacket;
+ myPacket << "Hello world!" << 123;
+ protocol.send(myPacket);
+ \endcode
+
+ As long as both ends of the connection are using the QPacketProtocol class,
+ the data within this packet will be delivered unfragmented at the other end,
+ ready for extraction.
+
+ \code
+ QByteArray greeting;
+ int count;
+
+ QPacket myPacket = protocol.read();
+
+ myPacket >> greeting >> count;
+ \endcode
+
+ Only packets returned from QPacketProtocol::read() may be read from. QPacket
+ instances constructed by directly by applications are for transmission only
+ and are considered "write only". Attempting to read data from them will
+ result in undefined behaviour.
+
+ \ingroup io
+ \sa QPacketProtocol
+ */
+
+/*!
+ Constructs an empty write-only packet.
+ */
+QPacket::QPacket()
+: QDataStream(), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::WriteOnly);
+ setDevice(buf);
+}
+
+/*!
+ Destroys the QPacket instance.
+ */
+QPacket::~QPacket()
+{
+ if(buf) {
+ delete buf;
+ buf = 0;
+ }
+}
+
+/*!
+ Creates a copy of \a other. The initial stream positions are shared, but the
+ two packets are otherwise independant.
+ */
+QPacket::QPacket(const QPacket & other)
+: QDataStream(), b(other.b), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(other.buf->openMode());
+ setDevice(buf);
+}
+
+/*!
+ \internal
+ */
+QPacket::QPacket(const QByteArray & ba)
+: QDataStream(), b(ba), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::ReadOnly);
+ setDevice(buf);
+}
+
+/*!
+ Returns true if this packet is empty - that is, contains no data.
+ */
+bool QPacket::isEmpty() const
+{
+ return b.isEmpty();
+}
+
+/*!
+ Clears data in the packet. This is useful for reusing one writable packet.
+ For example
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket packet;
+
+ packet << "Hello world!" << 123;
+ protocol.send(packet);
+
+ packet.clear();
+ packet << "Goodbyte world!" << 789;
+ protocol.send(packet);
+ \endcode
+ */
+void QPacket::clear()
+{
+ QBuffer::OpenMode oldMode = buf->openMode();
+ buf->close();
+ b.clear();
+ buf->setBuffer(&b); // reset QBuffer internals with new size of b.
+ buf->open(oldMode);
+}
+
+/*!
+ \class QPacketAutoSend
+ \inpublicgroup QtBaseModule
+
+ \internal
+ */
+QPacketAutoSend::QPacketAutoSend(QPacketProtocol * _p)
+: QPacket(), p(_p)
+{
+}
+
+QPacketAutoSend::~QPacketAutoSend()
+{
+ if(!b.isEmpty())
+ p->send(*this);
+}
+
+#include "qpacketprotocol.moc"
+
diff --git a/src/declarative/debugger/qpacketprotocol.h b/src/declarative/debugger/qpacketprotocol.h
new file mode 100644
index 0000000..6dd8bda
--- /dev/null
+++ b/src/declarative/debugger/qpacketprotocol.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPACKETPROTOCOL_H
+#define QPACKETPROTOCOL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qdatastream.h>
+
+class QIODevice;
+class QBuffer;
+class QPacket;
+class QPacketAutoSend;
+class QPacketProtocolPrivate;
+
+class Q_DECLARATIVE_EXPORT QPacketProtocol : public QObject
+{
+Q_OBJECT
+public:
+ explicit QPacketProtocol(QIODevice * dev, QObject * parent = 0);
+ virtual ~QPacketProtocol();
+
+ qint32 maximumPacketSize() const;
+ qint32 setMaximumPacketSize(qint32);
+
+ QPacketAutoSend send();
+ void send(const QPacket &);
+
+ qint64 packetsAvailable() const;
+ QPacket read();
+
+ void clear();
+
+ QIODevice * device();
+
+signals:
+ void readyRead();
+ void invalidPacket();
+ void packetWritten();
+
+private:
+ QPacketProtocolPrivate * d;
+};
+
+
+class Q_DECLARATIVE_EXPORT QPacket : public QDataStream
+{
+public:
+ QPacket();
+ QPacket(const QPacket &);
+ virtual ~QPacket();
+
+ void clear();
+ bool isEmpty() const;
+
+protected:
+ friend class QPacketProtocol;
+ QPacket(const QByteArray & ba);
+ QByteArray b;
+ QBuffer * buf;
+};
+
+class Q_DECLARATIVE_EXPORT QPacketAutoSend : public QPacket
+{
+public:
+ virtual ~QPacketAutoSend();
+
+private:
+ friend class QPacketProtocol;
+ QPacketAutoSend(QPacketProtocol *);
+ QPacketProtocol * p;
+};
+
+#endif
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
new file mode 100644
index 0000000..382f3cb
--- /dev/null
+++ b/src/declarative/declarative.pro
@@ -0,0 +1,31 @@
+TARGET = QtDeclarative
+QPRO_PWD = $$PWD
+QT = core gui xml script network
+contains(QT_CONFIG, svg): QT += svg
+DEFINES += QT_BUILD_DECLARATIVE_LIB
+DEFINES += QT_NO_USING_NAMESPACE
+win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000
+solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+
+unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui QtXml
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
+
+include(../qbase.pri)
+
+#modules
+include(3rdparty/3rdparty.pri)
+include(util/util.pri)
+include(fx/fx.pri)
+include(canvas/canvas.pri)
+include(qml/qml.pri)
+include(timeline/timeline.pri)
+include(extra/extra.pri)
+include(widgets/widgets.pri)
+include(test/test.pri)
+include(debugger/debugger.pri)
+
+contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1):include(opengl/opengl.pri)
+
+symbian:TARGET.UID3=0x2001E623
diff --git a/src/declarative/extra/extra.pri b/src/declarative/extra/extra.pri
new file mode 100644
index 0000000..83978f1
--- /dev/null
+++ b/src/declarative/extra/extra.pri
@@ -0,0 +1,24 @@
+SOURCES += \
+ extra/qnumberformat.cpp \
+ extra/qmlnumberformatter.cpp \
+ extra/qfxintegermodel.cpp
+
+HEADERS += \
+ extra/qnumberformat.h \
+ extra/qmlnumberformatter.h \
+ extra/qfxintegermodel.h
+
+contains(QT_CONFIG, xmlpatterns) {
+ QT+=xmlpatterns
+ SOURCES += extra/qmlxmllistmodel.cpp
+ HEADERS += extra/qmlxmllistmodel.h
+}
+
+# SQL is permanently enabled :-/
+#contains(QT_CONFIG, sql) {
+ QT+= sql
+ SOURCES += extra/qmlsqlquery.cpp \
+ extra/qmlsqlconnection.cpp
+ HEADERS += extra/qmlsqlquery.h \
+ extra/qmlsqlconnection.h
+#}
diff --git a/src/declarative/extra/qfxintegermodel.cpp b/src/declarative/extra/qfxintegermodel.cpp
new file mode 100644
index 0000000..2a85ee1
--- /dev/null
+++ b/src/declarative/extra/qfxintegermodel.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxintegermodel.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxIntegerModel, IntegerModel)
+
+class QFxIntegerModelPrivate
+{
+public:
+ QFxIntegerModelPrivate() : min(0), max(0) {}
+ int min;
+ int max;
+};
+
+QFxIntegerModel::QFxIntegerModel(QObject *parent)
+ : QListModelInterface(parent)
+{
+ d = new QFxIntegerModelPrivate;
+}
+
+QFxIntegerModel::~QFxIntegerModel()
+{
+ delete d;
+}
+
+int QFxIntegerModel::minimum() const
+{
+ return d->min;
+}
+
+void QFxIntegerModel::setMinimum(int min)
+{
+ d->min = min;
+}
+
+int QFxIntegerModel::maximum() const
+{
+ return d->max;
+}
+
+void QFxIntegerModel::setMaximum(int max)
+{
+ d->max = max;
+}
+
+int QFxIntegerModel::count() const
+{
+ return qMax(0, d->max - d->min + 1);
+}
+
+QHash<int,QVariant> QFxIntegerModel::data(int index, const QList<int> &roles) const
+{
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case Qt::DisplayRole:
+ info = QVariant(QString::number(d->min+index));
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+}
+
+QString QFxIntegerModel::toString(int role) const
+{
+ switch(role) {
+ case Qt::DisplayRole:
+ return QLatin1String("display");
+ default:
+ return QLatin1String("");
+ }
+}
+
+QList<int> QFxIntegerModel::roles() const
+{
+ return QList<int>() << Qt::DisplayRole;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qfxintegermodel.h b/src/declarative/extra/qfxintegermodel.h
new file mode 100644
index 0000000..43504d8
--- /dev/null
+++ b/src/declarative/extra/qfxintegermodel.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXINTMODEL_H
+#define QFXINTMODEL_H
+
+#include <QtCore/QObject>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qlistmodelinterface.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxIntegerModelPrivate;
+class Q_DECLARATIVE_EXPORT QFxIntegerModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ QFxIntegerModel(QObject *parent=0);
+ ~QFxIntegerModel();
+
+ Q_PROPERTY(int minimum READ minimum WRITE setMinimum)
+ int minimum() const;
+ void setMinimum(int);
+
+ Q_PROPERTY(int maximum READ maximum WRITE setMaximum)
+ int maximum() const;
+ void setMaximum(int);
+
+ int count() const;
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const;
+ QList<int> roles() const;
+ QString toString(int role) const;
+
+private:
+ QFxIntegerModelPrivate *d;
+};
+
+QML_DECLARE_TYPE(QFxIntegerModel)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/extra/qmlnumberformatter.cpp b/src/declarative/extra/qmlnumberformatter.cpp
new file mode 100644
index 0000000..1549525
--- /dev/null
+++ b/src/declarative/extra/qmlnumberformatter.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlnumberformatter.h"
+#include "private/qobject_p.h"
+
+
+QT_BEGIN_NAMESPACE
+//TODO: set locale
+// docs
+// this is a wrapper around qnumberformat (test integration)
+// if number or format haven't been explictly set, text should be an empty string
+
+class QmlNumberFormatterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlNumberFormatter)
+public:
+ QmlNumberFormatterPrivate() : locale(QLocale::system()), number(0), classComplete(true) {}
+
+ void updateText();
+
+ QLocale locale;
+ QString format;
+ QNumberFormat numberFormat;
+ QString text;
+ qreal number;
+ bool classComplete;
+};
+/*!
+ \qmlclass NumberFormatter
+ \brief The NumberFormatter allows you to control the format of a number string.
+
+ The format property documentation has more details on how the format can be manipulated.
+
+ In the following example, the text element will display the text "1,234.57".
+ \code
+ NumberFormatter { id: Formatter; number: 1234.5678; format: "##,##0.##" }
+ Text { text: Formatter.text }
+ \endcode
+
+ */
+/*!
+ \internal
+ \class QmlNumberFormatter
+ \ingroup group_utility
+ \brief The QmlNumberFormatter class allows you to format a number to a particular string format/locale specific number format.
+*/
+
+QmlNumberFormatter::QmlNumberFormatter(QObject *parent)
+: QObject(*(new QmlNumberFormatterPrivate), parent)
+{
+}
+
+QmlNumberFormatter::~QmlNumberFormatter()
+{
+}
+
+/*!
+ \qmlproperty string NumberFormatter::text
+
+ The number in the specified format.
+ <br>
+ If no format is specified the text will be empty.
+*/
+
+QString QmlNumberFormatter::text() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->text;
+}
+
+/*!
+ \qmlproperty qreal NumberFormatter::number
+
+ A single point precision number. (Doubles are not yet supported)
+
+*/
+qreal QmlNumberFormatter::number() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->number;
+}
+
+/*!
+ \qmlproperty string NumberFormatter::format
+
+ The particular format the number will adhere to during the conversion to text.
+ <br>
+ The format syntax follows a style similar to the Unicode Standard (UTS35).
+
+ The table below shows the characters, patterns that can be used in the format.
+
+ <table border="0" align="center">
+ <tr style="background-color: #D6E2E8"><th> Character </th><th> Meaning </th></tr>
+ <tr><td> # </td><td> Any digit(s), zero shows as absent (for leading/trailing zeroes) </td></tr>
+ <tr><td> 0 </td><td> Implicit digit. Zero will show in the case that the input number is too small.</td></tr>
+ <tr><td> . </td><td> Decimal separator. Output decimal seperator will be dependant on system locale.</td></tr>
+ <tr><td> , </td><td> Grouping separator. The number of digits (either #, or 0) between the grouping separator and the decimal (or the rightmost digit) will determine the groupingSize)</td></tr>
+ <tr><td> other </td><td> Any other character will be taken as a string literal and placed directly into the output string </td></tr>
+ </table>
+
+ Invalid formats will not guarantee a meaningful text output.<br>
+
+ \note <i>Input numbers that are too long for the given format will be rounded dependent on precison based on the position of the decimal point </i>
+
+ The following table illustrates the output text created by applying some examples of numeric formats to the formatter.
+
+ <table border="0" align="center">
+ <tr style="background-color: #D6E2E8"><th> Format </th><th> Number </th><th> Output </th></tr>
+ <tr><td> ### </td><td> 123456 </td><td> 123456 </td></tr>
+ <tr><td> 000 </td><td> 123456 </td><td> 123456 </td></tr>
+ <tr><td> ###### </td><td> 1234 </td><td> 1234 </td></tr>
+ <tr><td> 000000 </td><td> 1234 </td><td> 001234 </td></tr>
+ <tr><td> ##,##0.## </td><td> 1234.456 </td><td> 1,234.46 (for US locale)<br> 1 234,46 (for FR locale)</td></tr>
+ <tr><td> 000000,000.# </td><td> 123456 </td><td> 000,123,456 (for US locale)<br> 000 123 456 (for FR locale)</td></tr>
+ <tr><td> 0.0### </td><td> 0.999997 </td><td> 1.0 </td></tr>
+ <tr><td> (000) 000 - 000 </td><td> 12345678 </td><td> (012) 345 - 678 </td></tr>
+ <tr><td> #A</td><td>12</td><td>12A</td></tr>
+ </table>
+
+*/
+QString QmlNumberFormatter::format() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->format;
+}
+
+void QmlNumberFormatter::setNumber(const qreal &number)
+{
+ Q_D(QmlNumberFormatter);
+ if (d->number == number)
+ return;
+ d->number = number;
+ d->updateText();
+}
+
+void QmlNumberFormatter::setFormat(const QString &format)
+{
+ Q_D(QmlNumberFormatter);
+ //no format checking
+ if (format.isEmpty())
+ d->format = QString::null;
+ else
+ d->format = format;
+ d->updateText();
+}
+
+void QmlNumberFormatterPrivate::updateText()
+{
+ Q_Q(QmlNumberFormatter);
+ if (!classComplete)
+ return;
+
+ QNumberFormat tempFormat;
+ tempFormat.setFormat(format);
+ tempFormat.setNumber(number);
+
+ text = tempFormat.text();
+
+ emit q->textChanged();
+}
+
+void QmlNumberFormatter::classBegin()
+{
+ Q_D(QmlNumberFormatter);
+ d->classComplete = false;
+}
+
+void QmlNumberFormatter::classComplete()
+{
+ Q_D(QmlNumberFormatter);
+ d->classComplete = true;
+ d->updateText();
+}
+
+QML_DEFINE_TYPE(QmlNumberFormatter, NumberFormatter);
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlnumberformatter.h b/src/declarative/extra/qmlnumberformatter.h
new file mode 100644
index 0000000..e4efc03
--- /dev/null
+++ b/src/declarative/extra/qmlnumberformatter.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLNUMBERFORMATTER_H
+#define QMLNUMBERFORMATTER_H
+
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qnumberformat.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlNumberFormatterPrivate;
+class Q_DECLARATIVE_EXPORT QmlNumberFormatter : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
+ Q_PROPERTY(QString format READ format WRITE setFormat)
+ Q_PROPERTY(qreal number READ number WRITE setNumber)
+public:
+ QmlNumberFormatter(QObject *parent=0);
+ ~QmlNumberFormatter();
+
+ QString text() const;
+
+ qreal number() const;
+ void setNumber(const qreal &);
+
+ QString format() const;
+ void setFormat(const QString &);
+
+ virtual void classBegin();
+ virtual void classComplete();
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ Q_DISABLE_COPY(QmlNumberFormatter)
+ Q_DECLARE_PRIVATE(QmlNumberFormatter)
+};
+
+QML_DECLARE_TYPE(QmlNumberFormatter)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/extra/qmlsqlconnection.cpp b/src/declarative/extra/qmlsqlconnection.cpp
new file mode 100644
index 0000000..b65fe35
--- /dev/null
+++ b/src/declarative/extra/qmlsqlconnection.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlsqlconnection.h"
+#include "private/qobject_p.h"
+
+#include <QSqlError>
+#include <QSqlDriver>
+#include <QDebug>
+
+#include <qml.h>
+#include <qmlcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(QmlSqlConnection, SqlConnection)
+
+class QmlSqlConnectionPrivate: public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSqlConnection)
+public:
+ QmlSqlConnectionPrivate() : port(0) {}
+
+ int port;
+ QString name, databaseName, connectionOptions;
+ QString hostName, userName, password, driver;
+};
+
+/*!
+ \qmlclass SqlConnection QmlSqlConnection
+ \brief The SqlConnection element describes a connection to an SQL database.
+
+ The SqlConnection element works in a similar way to
+ QSqlDatabase::addDatabase(). It allows setting the database properties
+ such that the connection does not need to be set up in C++ code.
+ It differs from QSqlDatabase::addDatabase() in that it will automatically
+ open the database.
+
+ The database can then either be used from an SqlQuery element using its id
+ as a bind, or using its name. If the database is set up externally to
+ Qml the query should connect using its name.
+
+ \qml
+ SqlConnection {
+ id: myConnection
+ name: "qmlConnection"
+ driver: "QSQLITE"
+ databaseName: "mydb.sqlite"
+ }
+ SqlQuery { id: listmodel; connection: myConnection; query: "SELECT * FROM mytable" }
+ SqlQuery { id: othermodel; connection: "qmlConnection"; query: "SELECT * FROM myothertable" }
+ \endqml
+*/
+
+/*!
+ \qmlproperty QString SqlConnection::name
+ \default
+
+ Defines the connection's name. The name allows the connection to be
+ retrieved using the connection property of SqlQuery or when
+ QSqlDatabase::database()
+*/
+
+/*!
+ \qmlproperty list<string> SqlConnection::tables
+
+ Defines the set of tables that exist in the database for the connection.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::databaseName
+
+ Defines the connection's database name. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::driver
+
+ Defines the driver type of the connection. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::connectOptions
+
+ Defines the options used when connecting to the database. These are used
+ when opening the connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::hostName
+
+ Defines the connection's host name. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty int SqlConnection::port
+
+ Defines the connection's port number. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::userName
+
+ Defines the connection's user name. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::password
+
+ Defines the connection's password. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::lastError
+
+ Defines the last error, if one occurred, when working with the database.
+ If the error occurred in conjunction with an SQL query the error will be
+ defined by SqlQuery::lastError.
+*/
+
+/*!
+ \internal
+ \class QmlSqlConnection
+ \brief The QmlSqlConnection class manages a connection to an SQL database.
+*/
+
+/*!
+ Constructs a QmlSqlConnection with the given \a parent.
+*/
+QmlSqlConnection::QmlSqlConnection(QObject *parent)
+: QObject(*(new QmlSqlConnectionPrivate), parent)
+{
+}
+
+/*!
+ Destroys the QmlSqlConnection.
+*/
+QmlSqlConnection::~QmlSqlConnection()
+{
+ QSqlDatabase db = database();
+ if (db.isOpen())
+ db.close();
+}
+
+/*!
+ Returns the connection's name.
+ This is equivalent to QSqlDatabase::connectionName().
+ \sa setName()
+*/
+QString QmlSqlConnection::name() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->name;
+}
+
+/*!
+ Returns the connection's database name.
+ This is equivalent to QSqlDatabase::databaseName().
+ \sa setDatabaseName()
+*/
+QString QmlSqlConnection::databaseName() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->databaseName;
+}
+
+/*!
+ Returns the connect options string used for this connection.
+
+ \sa setConnectOptions()
+*/
+QString QmlSqlConnection::connectOptions() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->connectionOptions;
+}
+
+/*!
+ Returns the connection's host name.
+ \sa setHostName()
+*/
+QString QmlSqlConnection::hostName() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->hostName;
+}
+
+/*!
+ Returns the connection's port number. The value is undefined if the port
+ number has not been set.
+
+ \sa setPort()
+*/
+int QmlSqlConnection::port() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->port;
+}
+
+/*!
+ Returns the connection's user name.
+
+ \sa setUserName()
+*/
+QString QmlSqlConnection::userName() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->userName;
+}
+
+/*!
+ Returns the connection's password.
+
+ \sa setPassword)()
+*/
+QString QmlSqlConnection::password() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->password;
+}
+
+/*!
+ Returns the connection's driver name.
+
+ \sa setDriver()
+*/
+QString QmlSqlConnection::driver() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->driver;
+}
+
+/*!
+ Returns a list of the database's tables.
+*/
+QStringList QmlSqlConnection::tables() const
+{
+ return database().tables();
+}
+
+/*!
+ Sets the connection's name to the given \a name.
+
+ \sa name()
+*/
+void QmlSqlConnection::setName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->name = name;
+}
+
+/*!
+ Set's the connection's database name to the given \a name.
+
+ \sa databaseName()
+*/
+void QmlSqlConnection::setDatabaseName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->databaseName = name;
+}
+
+/*!
+ Sets the connection's options to the given \a options.
+
+ \sa connectOptions(), QSqlDatabase::setConnectOptions()
+*/
+void QmlSqlConnection::setConnectOptions(const QString &options)
+{
+ Q_D(QmlSqlConnection);
+ d->connectionOptions = options;
+}
+
+/*!
+ Sets the connection's host name to the given \a name.
+
+ \sa hostName()
+*/
+void QmlSqlConnection::setHostName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->hostName = name;
+}
+
+/*!
+ Sets the connection's port number to the given \a port.
+
+ \sa port()
+*/
+void QmlSqlConnection::setPort(int port)
+{
+ Q_D(QmlSqlConnection);
+ d->port = port;
+}
+
+/*!
+ Sets the connection's user name to the given \a name.
+
+ \sa userName()
+*/
+void QmlSqlConnection::setUserName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->userName = name;
+}
+
+/*!
+ Sets the connection's password to the given \a password.
+
+ \sa password()
+*/
+void QmlSqlConnection::setPassword(const QString &password)
+{
+ Q_D(QmlSqlConnection);
+ d->password = password;
+}
+
+/*!
+ Returns information about the last error that occurred on the database.
+
+ Failures that occur in conjunction with an individual query are
+ reported by QmlSqlQuery::lastError()
+*/
+QString QmlSqlConnection::lastError() const
+{
+ return database().lastError().text();
+}
+
+/*!
+ Sets the connection's driver to the specified driver \a type.
+
+ \sa driver(), QSqlDatabase::addDatabase()
+*/
+void QmlSqlConnection::setDriver(const QString &type)
+{
+ Q_D(QmlSqlConnection);
+ d->driver = type;
+}
+
+/*!
+ \reimp
+*/
+void QmlSqlConnection::classComplete()
+{
+}
+
+/*!
+ Returns the database object associated with this connection.
+ If the database is not yet open, it will open the database
+ passed on the settings specified for the SQL connection.
+*/
+QSqlDatabase QmlSqlConnection::database() const
+{
+ Q_D(const QmlSqlConnection);
+
+ QSqlDatabase db;
+ if (QSqlDatabase::connectionNames().contains(d->name)) {
+ db = QSqlDatabase::database(d->name);
+ } else {
+ db = QSqlDatabase::addDatabase(
+ d->driver.isEmpty()
+ ? QLatin1String("QSQLITE")
+ : d->driver,
+ d->name.isEmpty()
+ ? QLatin1String(QSqlDatabase::defaultConnection)
+ : d->name);
+ }
+ if (db.isOpen())
+ return db;
+ if ((d->driver.isEmpty() || d->driver == QLatin1String("QSQLITE")) &&
+ qmlContext(this)) {
+ // SQLITE uses files for databases, hence use relative pathing
+ // if possible.
+ QUrl url = qmlContext(this)->resolvedUrl(d->databaseName);
+ if (url.isRelative() || url.scheme() == QLatin1String("file"))
+ db.setDatabaseName(url.toLocalFile());
+ else
+ db.setDatabaseName(d->databaseName);
+ } else {
+ db.setDatabaseName(d->databaseName);
+ }
+ db.setConnectOptions(d->connectionOptions);
+ db.setHostName(d->hostName);
+ db.setPassword(d->password);
+ db.setPort(d->port);
+ db.setUserName(d->userName);
+ if (!db.open())
+ qWarning() << "Failed to open database" << lastError();
+
+ return db;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlsqlconnection.h b/src/declarative/extra/qmlsqlconnection.h
new file mode 100644
index 0000000..306db8d
--- /dev/null
+++ b/src/declarative/extra/qmlsqlconnection.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSQLCONNECTION_H
+#define QMLSQLCONNECTION_H
+
+#include <QtDeclarative/qml.h>
+#include <QtSql/QSqlDatabase>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QSqlDatabase;
+class QmlSqlConnectionPrivate;
+class Q_DECLARATIVE_EXPORT QmlSqlConnection : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QStringList tables READ tables)
+ Q_PROPERTY(QString databaseName READ databaseName WRITE setDatabaseName)
+ Q_PROPERTY(QString driver READ driver WRITE setDriver)
+ Q_PROPERTY(QString connectOptions READ connectOptions WRITE setConnectOptions)
+ Q_PROPERTY(QString hostName READ hostName WRITE setHostName)
+ Q_PROPERTY(int port READ port WRITE setPort)
+ Q_PROPERTY(QString userName READ userName WRITE setUserName)
+ Q_PROPERTY(QString password READ password WRITE setPassword)
+ Q_PROPERTY(QString lastError READ lastError)
+ Q_CLASSINFO("DefaultProperty", "name")
+public:
+ QmlSqlConnection(QObject *parent = 0);
+ ~QmlSqlConnection();
+
+ QString name() const;
+ void setName(const QString &);
+
+ QStringList tables() const;
+
+ QString databaseName() const;
+ void setDatabaseName(const QString &);
+
+ QString connectOptions() const;
+ void setConnectOptions(const QString &);
+
+ QString hostName() const;
+ void setHostName(const QString &);
+
+ int port() const;
+ void setPort(int);
+
+ QString userName() const;
+ void setUserName(const QString &);
+
+ QString password() const;
+ void setPassword(const QString &);
+
+ QString driver() const;
+ void setDriver(const QString &);
+
+ QString lastError() const;
+
+ virtual void classComplete();
+
+ QSqlDatabase database() const;
+private:
+ Q_DISABLE_COPY(QmlSqlConnection)
+ Q_DECLARE_PRIVATE(QmlSqlConnection)
+};
+
+QML_DECLARE_TYPE(QmlSqlConnection)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLXMLLISTMODEL_H
+
diff --git a/src/declarative/extra/qmlsqlquery.cpp b/src/declarative/extra/qmlsqlquery.cpp
new file mode 100644
index 0000000..0e2e91b
--- /dev/null
+++ b/src/declarative/extra/qmlsqlquery.cpp
@@ -0,0 +1,694 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlsqlquery.h"
+#include "qmlsqlconnection.h"
+#include "private/qobject_p.h"
+
+#include <QDebug>
+#include <QSqlQuery>
+#include <QSqlError>
+#include <QSqlField>
+#include <QSqlRecord>
+#include <QSqlDatabase>
+#include <QSqlDriver>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QmlSqlBind, SqlBind)
+QML_DEFINE_TYPE(QmlSqlQuery, SqlQuery)
+
+class QmlSqlBindPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSqlBind)
+public:
+ QmlSqlBindPrivate() {}
+
+ QString name;
+ QVariant value;
+};
+
+/*!
+ \qmlclass SqlBind QmlSqlBind
+ \brief The SqlBind element specifies a value binding for an SqlQuery element.
+
+ By using bindings its possible to cause a SqlQuery to update itself
+ when values bound through the SqlBind change. Hence in the example
+ below the results for the SqlQuery will change as searchText changes.
+
+ If the query is not a SELECT statement, the effects of the bound
+ values will only apply when the SqlQuery exec() slot is called.
+
+ \qml
+ SqlQuery {
+ query: "SELECT * FROM mytable WHERE name LIKE :value"
+ bindings: SqlBind {
+ name: ":value"
+ value: searchText + '%'
+ }
+ }
+ SqlQuery {
+ query: "SELECT * FROM mytable WHERE type = ?"
+ bindings: SqlBind {
+ value: "simple"
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \internal
+ \class QmlSqlBind
+ \brief The QmlSqlBind class specifies a value binding for a QmlSqlQuery.
+*/
+
+/*!
+ \fn void QmlSqlBind::valueChanged()
+
+ This signal is emitted when the value property of the SqlBind changes.
+*/
+
+/*!
+ \qmlproperty QString SqlBind::name
+
+ Defines the placeholder name of the bind. If no name is specified the
+ bind will use its position within the SqlQuery's bindings to bind
+ into the query.
+*/
+
+/*!
+ \qmlproperty QVariant SqlBind::value
+
+ Defines the value to bind into the query.
+*/
+
+/*!
+ Constructs a QmlSqlVind with the given \a parent
+*/
+QmlSqlBind::QmlSqlBind(QObject *parent)
+: QObject(*(new QmlSqlBindPrivate()), parent)
+{
+}
+
+/*!
+ Destroys the QmlSqlBind.
+*/
+QmlSqlBind::~QmlSqlBind()
+{
+}
+
+/*!
+ Returns the binding's name.
+
+ \sa setName()
+*/
+QString QmlSqlBind::name() const
+{
+ Q_D(const QmlSqlBind);
+ return d->name;
+}
+
+/*!
+ Returns the binding's value.
+
+ \sa setValue()
+*/
+QVariant QmlSqlBind::value() const
+{
+ Q_D(const QmlSqlBind);
+ return d->value;
+}
+
+/*!
+ Sets the binding's name to the given \a name.
+
+ \sa name()
+*/
+void QmlSqlBind::setName(const QString &name)
+{
+ Q_D(QmlSqlBind);
+ d->name = name;
+}
+
+/*!
+ Sets the binding's value to the given \a value.
+
+ \sa value()
+*/
+void QmlSqlBind::setValue(const QVariant &value)
+{
+ Q_D(QmlSqlBind);
+ if (d->value != value) {
+ d->value = value;
+ emit valueChanged();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QmlSqlBind::classComplete()
+{
+}
+
+class QmlSqlQueryPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSqlQuery)
+public:
+ QmlSqlQueryPrivate(QmlSqlQuery *owner) : isSel(false), query(NULL), requireCache(false), count(-1), binds(owner) {}
+ void prepareQuery() const;
+ void bindQuery() const;
+ void cacheQuery() const;
+ void grabRoles() const;
+
+ QString queryText;
+ bool isSel;
+ QVariant connectionVariant;
+ mutable QSqlQuery *query;
+ mutable bool requireCache;
+ mutable int count;
+ mutable QList<int> roles;
+ mutable QStringList roleNames;
+ mutable QVector< QVector< QVariant > > cache;
+
+ class QmlSqlBindList : public QmlList<QmlSqlBind *>
+ {
+ public:
+ QmlSqlBindList(QmlSqlQuery *owner)
+ : q(owner){}
+
+ void append(QmlSqlBind *o) {
+ m_contents.append(o);
+ QObject::connect(o, SIGNAL(valueChanged()), q, SLOT(resetBinds()));
+ }
+ void clear() { m_contents.clear(); }
+ int count() const { return m_contents.count(); }
+ void removeAt(int pos) { return m_contents.removeAt(pos); }
+ QmlSqlBind *at(int pos) const { return m_contents.at(pos); }
+ void insert(int pos, QmlSqlBind *o) { m_contents.insert(pos, o); }
+ private:
+ QList<QmlSqlBind *> m_contents;
+ QmlSqlQuery *q;
+ };
+
+ QmlSqlBindList binds;
+};
+
+/*!
+ \qmlclass SqlQuery QmlSqlQuery
+ \brief The SqlQuery element describes a query into an SQL database.
+
+ The SqlQuery element has three parts. The first is the query itself,
+ which can either be specified using the query property or by the
+ default text for the element. The second specifies the connection
+ to the database. This can either be a bound id from an SqlConnection
+ or the connections name. If the connection is specified in a QML
+ SqlConnection it is recommend to bind to the id to help ensure the
+ database is complete before attempting to attach to it. If no
+ connectoin is specified the default connection is used.
+
+ It is also possible to bind values into the query using the bindings
+ property. See SqlBind for more information on how to bind values into
+ the query.
+
+ If the query is a select statement it can be used as a model for a ListView.
+ The roles will be the columns of the result set. Use the SQL AS keyword
+ in the query if you want to override the column names from that of the
+ table selected. You should also use the AS keyword if there is no
+ appropriate table column name for the result column.
+
+ \qml
+ SqlQuery { connection: qmlConnectionId; query: "DELETE FROM mytable" }
+ SqlQuery {
+ connection: "connectionName"
+ query: "SELECT * FROM mytable"
+ }
+ SqlQuery { query: "SELECT id AS recordId, (firstName || ' ' || lastName) AS fullName FROM mytable" }
+ \endqml
+*/
+
+/*
+ \class QmlSqlQuery
+ \brief the QmlSqlQuery class manages a query into an SQL database.
+*/
+
+/*!
+ \qmlproperty QString SqlQuery::query
+ \default
+
+ Defines the query text.
+*/
+
+/*!
+ \qmlproperty QVariant SqlQuery::connection
+
+ Defines the connection to an SQL database used by the query.
+*/
+
+/*!
+ \qmlproperty QString SqlQuery::lastError
+
+ Defines the last error, if one occurred, when working with the query.
+*/
+
+/*!
+ \qmlproperty list<SqlBind> SqlQuery::bindings
+
+ The bindings property contains the list of values to bind into the
+ query. See SqlBind for more information.
+*/
+
+/*!
+ Constructs a QmlSqlQuery with the given \a parent.
+*/
+QmlSqlQuery::QmlSqlQuery(QObject *parent)
+: QListModelInterface(*(new QmlSqlQueryPrivate(this)), parent)
+{
+}
+
+/*!
+ Destroys the QmlSqlQuery.
+*/
+QmlSqlQuery::~QmlSqlQuery()
+{
+ Q_D(QmlSqlQuery);
+ if (d->query)
+ delete d->query;
+}
+
+/*!
+ Returns the query's bound variables.
+*/
+QmlList<QmlSqlBind *> *QmlSqlQuery::bindings()
+{
+ Q_D(QmlSqlQuery);
+ return &d->binds;
+}
+
+/*!
+ Returns the query's bound variables.
+*/
+const QmlList<QmlSqlBind *> *QmlSqlQuery::bindings() const
+{
+ Q_D(const QmlSqlQuery);
+ return &d->binds;
+}
+
+/*!
+ Returns the query text.
+
+ \sa setQuery()
+*/
+QString QmlSqlQuery::query() const
+{
+ Q_D(const QmlSqlQuery);
+ return d->queryText;
+}
+
+/*!
+ Sets the query text to the given \a text.
+*/
+void QmlSqlQuery::setQuery(const QString &text)
+{
+ Q_D(QmlSqlQuery);
+ if (text != d->queryText) {
+ d->queryText = text;
+
+ static const QLatin1String select("select");
+ d-> isSel = text.trimmed().indexOf(select, 0, Qt::CaseInsensitive) == 0;
+
+ if (d->query)
+ resetQuery();
+ }
+}
+
+/*!
+ Returns the query's connection specifier.
+
+ \sa setConnection()
+*/
+QVariant QmlSqlQuery::connection() const
+{
+ Q_D(const QmlSqlQuery);
+ return d->connectionVariant;
+}
+
+/*!
+ Sets the query's connection specifier.
+
+ \sa connection()
+*/
+void QmlSqlQuery::setConnection(const QVariant &connection)
+{
+ Q_D(QmlSqlQuery);
+ if (connection != d->connectionVariant) {
+ d->connectionVariant = connection;
+ if (d->query)
+ resetQuery();
+ else if (d->count == 0) // data has been requested
+ d->prepareQuery();
+ }
+}
+
+/*!
+ Returns the set of values for a given set of requested \a roles for the
+ specified \a row of the query result set. Returns an empty hash if the
+ query is not a select statement.
+
+ \sa count(), roles(), toString()
+*/
+QHash<int,QVariant> QmlSqlQuery::data(int row, const QList<int> &roles) const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+ QHash<int, QVariant> result;
+
+ if (!d->isSel)
+ return result;
+
+ Q_ASSERT(row >= 0 && row <= d->count);
+
+ if (!d->requireCache)
+ d->query->seek(row);
+
+ for (int i = 0; i < roles.count(); ++i) {
+ int column = roles[i];
+ Q_ASSERT(column >= 0 && column < d->cache.size());
+ if (d->requireCache)
+ result.insert(column, d->cache[column].at(row));
+ else
+ result.insert(column, d->query->value(column));
+ }
+ return result;
+}
+
+/*!
+ Returns the number of rows in the query result set. Returns 0 if
+ the query is not a select statement.
+
+ \sa data(), roles(), toString()
+*/
+int QmlSqlQuery::count() const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+ return d->count;
+}
+
+/*!
+ Returns the list of role integer identifiers for the query result set.
+ Returns and empty list if the query is not a select statement.
+
+ \sa data(), count(), toString()
+*/
+QList<int> QmlSqlQuery::roles() const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+
+ if (!d->isSel)
+ return QList<int>();
+
+ if (d->roleNames.isEmpty() && !d->requireCache) {
+ d->query->seek(0);
+ d->grabRoles();
+ }
+
+ return d->roles;
+}
+
+/*!
+ Returns the corresponding role name for the given \a role identifier.
+
+ \sa data(), roles(), toString()
+*/
+QString QmlSqlQuery::toString(int role) const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+
+ if (d->roleNames.isEmpty() && !d->requireCache) {
+ d->query->seek(0);
+ d->grabRoles();
+ }
+
+ return d->roleNames[role];
+}
+
+/*!
+ Returns information about the last error that occurred on the query.
+*/
+QString QmlSqlQuery::lastError() const
+{
+ Q_D(const QmlSqlQuery);
+ if (d->query)
+ return d->query->lastError().text();
+ return QString();
+}
+
+/*!
+ \reimp
+*/
+void QmlSqlQuery::classComplete()
+{
+ Q_D(QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+}
+
+/*!
+ \internal
+ Rebinds the query, and if needed, emits rows inserted or rows
+ added so any attached ListView elements will correctly.
+
+ This slot is called automatically when the SqlBind elements in
+ the bindings property of the query change.
+*/
+void QmlSqlQuery::resetBinds()
+{
+ Q_D(QmlSqlQuery);
+ if (!d->query)
+ return;
+ int oldcount = d->count;
+ d->cache.resize(0);
+ d->roles.clear();
+ d->roleNames.clear();
+ d->bindQuery();
+ if (d->isSel) {
+ if (!d->query->isActive()) {
+ if (!d->query->exec())
+ qWarning() << "failed to execute query" << d->query->lastQuery() << d->query->boundValues() << d->query->lastError().text();
+ }
+ d->cacheQuery(); // may finish query
+ emitChanges(oldcount);
+ }
+}
+
+/*!
+ Executes the query. For SELECT statements this is normally only required
+ if the database changes outside of the SQL query element. Statements that
+ modify the database, such as UPDATE and INSERT, will not be applied until
+ this function is called.
+*/
+void QmlSqlQuery::exec()
+{
+ Q_D(QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+ Q_ASSERT(d->query);
+
+ if (d->isSel) {
+ int oldcount = d->count;
+ d->cache.resize(0);
+ d->roles.clear();
+ d->roleNames.clear();
+ if (!d->query->exec())
+ qWarning() << "failed to execute query" << d->query->lastQuery() << d->query->boundValues() << d->query->lastError().text();
+ d->cacheQuery(); // may finish query
+ emitChanges(oldcount);
+ } else {
+ if (!d->query->exec())
+ qWarning() << "failed to execute query" << d->query->lastQuery() << d->query->boundValues() << d->query->lastError().text();
+ d->query->finish();
+ }
+}
+
+/*!
+ \internal
+
+ Resets the query and query cache.
+*/
+void QmlSqlQuery::resetQuery()
+{
+ Q_D(QmlSqlQuery);
+ Q_ASSERT(d->query != 0);
+ delete d->query;
+ d->query = 0;
+ d->cache.resize(0);
+ d->roles.clear();
+ d->roleNames.clear();
+ int oldcount = d->count;
+ d->prepareQuery();
+ emitChanges(oldcount);
+}
+
+/*!
+ \internal
+
+ emits row number changes based of differences between the given
+ \a oldcount and the current count of the query result set.
+*/
+void QmlSqlQuery::emitChanges(int oldcount)
+{
+ Q_D(QmlSqlQuery);
+ if (d->count > oldcount)
+ emit itemsInserted(oldcount, d->count-oldcount);
+ else if (d->count < oldcount)
+ emit itemsRemoved(d->count, oldcount-d->count);
+ if (d->count > 0 && oldcount > 0)
+ emit itemsChanged(0, qMin(d->count, oldcount), roles());
+}
+
+/*
+ Prepares the query. If the query starts with SELECT it is assumed to
+ be a SELECT statement and the query is also executed.
+*/
+void QmlSqlQueryPrivate::prepareQuery() const
+{
+ QObject *object = qvariant_cast<QObject*>(connectionVariant);
+ QmlSqlConnection *connection = qobject_cast<QmlSqlConnection *>(object);
+ QString connectionString = qvariant_cast<QString>(connectionVariant);
+
+ Q_ASSERT(query == 0);
+ QSqlDatabase db = connection ? connection->database()
+ : QSqlDatabase::database(connectionString.isEmpty()
+ ? QLatin1String(QSqlDatabase::defaultConnection)
+ : connectionString, false);
+
+ if (!db.isOpen()) {
+ count = 0;
+ return;
+ }
+
+ query = new QSqlQuery(db);
+
+ requireCache =
+ query->driver()->hasFeature(QSqlDriver::SimpleLocking)
+ || !query->driver()->hasFeature(QSqlDriver::QuerySize);
+
+ if (requireCache)
+ query->setForwardOnly(true);
+ if (!query->prepare(queryText))
+ qWarning() << "failed to prepare query" << query->lastQuery() << query->lastError().text();
+ bindQuery();
+ if (isSel) {
+ if (!query->exec())
+ qWarning() << "failed to execute query" << query->lastQuery() << query->boundValues() << query->lastError().text();
+ cacheQuery();
+ }
+}
+
+/*
+ Binds values into the prepared query using the bindings property of the SqlQuery element.
+*/
+void QmlSqlQueryPrivate::bindQuery() const
+{
+ for (int i = 0; i < binds.count(); ++i) {
+ QmlSqlBind *bind = binds.at(i);
+ if (bind->name().isEmpty()) {
+ query->bindValue(i, bind->value());
+ } else {
+ query->bindValue(bind->name(), bind->value());
+ }
+ }
+}
+
+/*
+ If the query is connected to a database with simple locking or
+ that cannot ask for the count of a result set, caches the required
+ data of the query and finishes the query to release locks.
+
+ Otherwise just caches the count of the query.
+*/
+void QmlSqlQueryPrivate::cacheQuery() const
+{
+ if (requireCache) {
+ int row = 0;
+ while (query->next()) {
+ if (roleNames.isEmpty()) {
+ grabRoles();
+ cache.resize(roleNames.count());
+ }
+ Q_ASSERT(cache.size() > 0);
+ for (int i = 0; i < cache.size(); ++i) {
+ cache[i].append(query->value(i));
+ }
+ row++;
+ }
+ count = row;
+ query->finish();
+ } else {
+ count = query->size();
+ }
+}
+
+/*
+ Gets the column names for the roles of the SqlQuery element.
+
+ The query must be active and on a valid row.
+*/
+void QmlSqlQueryPrivate::grabRoles() const
+{
+ Q_ASSERT(query);
+ Q_ASSERT(query->isValid());
+ Q_ASSERT(roleNames.isEmpty());
+ Q_ASSERT(roles.isEmpty());
+
+ QSqlRecord record = query->record();
+ for (int i = 0; i < record.count(); ++i) {
+ roleNames.append(record.fieldName(i));
+ roles.append(i);
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlsqlquery.h b/src/declarative/extra/qmlsqlquery.h
new file mode 100644
index 0000000..dca3596
--- /dev/null
+++ b/src/declarative/extra/qmlsqlquery.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSQLQUERYMODEL_H
+#define QMLSQLQUERYMODEL_H
+
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/QListModelInterface>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlSqlBindPrivate;
+class Q_DECLARATIVE_EXPORT QmlSqlBind : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+
+ Q_CLASSINFO("DefaultValue", "value")
+
+public:
+ QmlSqlBind(QObject *parent = 0);
+ ~QmlSqlBind();
+
+ QString name() const;
+ QVariant value() const;
+
+ void setName(const QString &name);
+ void setValue(const QVariant &);
+
+ virtual void classComplete();
+
+Q_SIGNALS:
+ void valueChanged();
+
+private:
+ Q_DISABLE_COPY(QmlSqlBind)
+ Q_DECLARE_PRIVATE(QmlSqlBind)
+};
+
+QML_DECLARE_TYPE(QmlSqlBind)
+
+class QSqlQuery;
+class QmlSqlQueryPrivate;
+class Q_DECLARATIVE_EXPORT QmlSqlQuery : public QListModelInterface, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(QVariant connection READ connection WRITE setConnection)
+ Q_PROPERTY(QString lastError READ lastError)
+
+ Q_PROPERTY(QmlList<QmlSqlBind *> *bindings READ bindings)
+
+ Q_CLASSINFO("DefaultProperty", "query")
+public:
+ QmlSqlQuery(QObject *parent = 0);
+ ~QmlSqlQuery();
+
+ QString query() const;
+ void setQuery(const QString &);
+
+ QVariant connection() const;
+ void setConnection(const QVariant &);
+
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual int count() const;
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+
+ QString lastError() const;
+
+ virtual void classComplete();
+
+ QmlList<QmlSqlBind *> *bindings();
+ const QmlList<QmlSqlBind *> *bindings() const;
+
+public slots:
+ void exec();
+
+private slots:
+ void resetBinds();
+ void resetQuery();
+
+private:
+ void emitChanges(int oldcount);
+
+ Q_DISABLE_COPY(QmlSqlQuery)
+ Q_DECLARE_PRIVATE(QmlSqlQuery)
+};
+
+QML_DECLARE_TYPE(QmlSqlQuery)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
+
diff --git a/src/declarative/extra/qmlxmllistmodel.cpp b/src/declarative/extra/qmlxmllistmodel.cpp
new file mode 100644
index 0000000..a7f5d72
--- /dev/null
+++ b/src/declarative/extra/qmlxmllistmodel.cpp
@@ -0,0 +1,536 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlxmllistmodel.h"
+#include "private/qobject_p.h"
+
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QDebug>
+#include <QApplication>
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QXmlQuery>
+#include <QXmlResultItems>
+#include <QXmlNodeModelIndex>
+#include <QBuffer>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(XmlListModelRole, Role)
+QML_DEFINE_TYPE(QmlXmlListModel, XmlListModel)
+
+
+class QmlXmlListModelPrivate;
+struct QmlXmlRoleList : public QmlConcreteList<XmlListModelRole *>
+{
+ QmlXmlRoleList(QmlXmlListModelPrivate *p)
+ : model(p) {}
+ virtual void append(XmlListModelRole *role);
+ //XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well
+ // (and the model should emit the appropriate signals)
+ virtual void clear();
+ virtual void removeAt(int i);
+ virtual void insert(int i, XmlListModelRole *role);
+
+ QmlXmlListModelPrivate *model;
+};
+
+
+
+class QmlXmlQuery : public QThread
+{
+ Q_OBJECT
+public:
+ QmlXmlQuery(QObject *parent=0)
+ : QThread(parent), m_quit(false), m_restart(false), m_abort(false), m_queryId(0) {
+ }
+ ~QmlXmlQuery() {
+ m_mutex.lock();
+ m_quit = true;
+ m_condition.wakeOne();
+ m_mutex.unlock();
+
+ wait();
+ }
+
+ void abort() {
+ QMutexLocker locker(&m_mutex);
+ m_abort = true;
+ }
+
+ int doQuery(QString query, QString namespaces, QByteArray data, QmlXmlRoleList *roleObjects) {
+ QMutexLocker locker(&m_mutex);
+ m_modelData.clear();
+ m_size = 0;
+ m_data = data;
+ m_query = query;
+ m_namespaces = namespaces;
+ m_roleObjects = roleObjects;
+ if (!isRunning()) {
+ m_abort = false;
+ start();
+ } else {
+ m_restart = true;
+ m_condition.wakeOne();
+ }
+ m_queryId++;
+ return m_queryId;
+ }
+
+ QList<QList<QVariant> > modelData() {
+ QMutexLocker locker(&m_mutex);
+ return m_modelData;
+ }
+
+signals:
+ void queryCompleted(int queryId, int size);
+
+protected:
+ void run() {
+ while (!m_quit) {
+ m_mutex.lock();
+ int queryId = m_queryId;
+ doQueryJob();
+ if (m_size > 0)
+ doSubQueryJob();
+ m_data.clear(); // no longer needed
+ m_mutex.unlock();
+
+ m_mutex.lock();
+ if (!m_abort && m_size > 0)
+ emit queryCompleted(queryId, m_size);
+ if (!m_restart)
+ m_condition.wait(&m_mutex);
+ m_abort = false;
+ m_restart = false;
+ m_mutex.unlock();
+ }
+ }
+
+private:
+ void doQueryJob();
+ void doSubQueryJob();
+
+private:
+ QMutex m_mutex;
+ QWaitCondition m_condition;
+ bool m_quit;
+ bool m_restart;
+ bool m_abort;
+ QByteArray m_data;
+ QString m_query;
+ QString m_namespaces;
+ QString m_prefix;
+ int m_size;
+ int m_queryId;
+ const QmlXmlRoleList *m_roleObjects;
+ QList<QList<QVariant> > m_modelData;
+};
+
+void QmlXmlQuery::doQueryJob()
+{
+ QString r;
+ QXmlQuery query;
+ QBuffer buffer(&m_data);
+ buffer.open(QIODevice::ReadOnly);
+ query.bindVariable(QLatin1String("src"), &buffer);
+ query.setQuery(m_namespaces + m_query);
+ query.evaluateTo(&r);
+
+ //qDebug() << r;
+
+ //always need a single root element
+ QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>";
+ QBuffer b(&xml);
+ b.open(QIODevice::ReadOnly);
+ //qDebug() << xml;
+
+ QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + m_namespaces;
+ QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
+ m_query.mid(m_query.lastIndexOf(QLatin1Char('/')));
+
+ //figure out how many items we are dealing with
+ int count = -1;
+ {
+ QXmlResultItems result;
+ QXmlQuery countquery;
+ countquery.bindVariable(QLatin1String("inputDocument"), &b);
+ countquery.setQuery(namespaces + QLatin1String("count(") + prefix + QLatin1String(")"));
+ countquery.evaluateTo(&result);
+ QXmlItem item(result.next());
+ if (item.isAtomicValue())
+ count = item.toAtomicValue().toInt();
+ prefix += QLatin1String("[%1]/");
+ }
+ //qDebug() << count;
+
+ m_prefix = namespaces + prefix;
+ m_data = xml;
+ if (count > 0)
+ m_size = count;
+}
+
+void QmlXmlQuery::doSubQueryJob()
+{
+ m_modelData.clear();
+
+ QBuffer b(&m_data);
+ b.open(QIODevice::ReadOnly);
+
+ QXmlQuery subquery;
+ subquery.bindVariable(QLatin1String("inputDocument"), &b);
+
+ //XXX should we use an array of objects or something else rather than a table?
+ for (int j = 0; j < m_size; ++j) {
+ QList<QVariant> resultList;
+ for (int i = 0; i < m_roleObjects->size(); ++i) {
+ XmlListModelRole *role = m_roleObjects->at(i);
+ subquery.setQuery(m_prefix.arg(j+1) + role->query());
+ if (role->isStringList()) {
+ QStringList data;
+ subquery.evaluateTo(&data);
+ resultList << QVariant(data);
+ //qDebug() << data;
+ } else {
+ QString s;
+ subquery.evaluateTo(&s);
+ if (role->isCData()) {
+ //un-escape
+ s.replace(QLatin1String("&lt;"), QLatin1String("<"));
+ s.replace(QLatin1String("&gt;"), QLatin1String(">"));
+ s.replace(QLatin1String("&amp;"), QLatin1String("&"));
+ }
+ resultList << s.trimmed();
+ //qDebug() << s;
+ }
+ b.seek(0);
+ }
+ m_modelData << resultList;
+ }
+}
+
+
+//TODO: do something smart while waiting for data to load
+// error handling (currently quite fragile)
+// profile doQuery and doSubquery
+// some sort of loading indication while we wait for initial data load (status property similar to QWebImage?)
+// support complex/nested objects?
+// how do we handle data updates (like rss feed -- usually items inserted at beginning)
+
+
+class QmlXmlListModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlXmlListModel)
+public:
+ QmlXmlListModelPrivate()
+ : isClassComplete(false), size(-1), highestRole(Qt::UserRole)
+ , reply(0), status(QmlXmlListModel::Idle), progress(0.0)
+ , queryId(-1), roleObjects(this) {}
+
+ bool isClassComplete;
+ QString src;
+ QString query;
+ QString namespaces;
+ int size;
+ QList<int> roles;
+ QStringList roleNames;
+ int highestRole;
+ QNetworkReply *reply;
+ QmlXmlListModel::Status status;
+ qreal progress;
+ QmlXmlQuery qmlXmlQuery;
+ int queryId;
+ QmlXmlRoleList roleObjects;
+ QList<QList<QVariant> > data;
+};
+
+
+void QmlXmlRoleList::append(XmlListModelRole *role) {
+ QmlConcreteList<XmlListModelRole *>::append(role);
+ model->roles << model->highestRole;
+ model->roleNames << role->name();
+ ++model->highestRole;
+}
+//XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well
+// (and the model should emit the appropriate signals)
+void QmlXmlRoleList::clear()
+{
+ model->roles.clear();
+ model->roleNames.clear();
+ QmlConcreteList<XmlListModelRole *>::clear();
+}
+void QmlXmlRoleList::removeAt(int i)
+{
+ model->roles.removeAt(i);
+ model->roleNames.removeAt(i);
+ QmlConcreteList<XmlListModelRole *>::removeAt(i);
+}
+void QmlXmlRoleList::insert(int i, XmlListModelRole *role)
+{
+ QmlConcreteList<XmlListModelRole *>::insert(i, role);
+ model->roles.insert(i, model->highestRole);
+ model->roleNames.insert(i, role->name());
+ ++model->highestRole;
+}
+
+/*!
+ \qmlclass XmlListModel
+ \brief The XmlListModel class allows you to specify a model using XQuery.
+
+ XmlListModel allows you to construct a model from XML data that can then be used as a data source
+ for the view classes (ListView, PathView, GridView) and any other classes that interact with model
+ data (like Repeater).
+
+ The following is an example of a model containing news from a Yahoo RSS feed:
+ \qml
+ XmlListModel {
+ id: FeedModel
+ source: "http://rss.news.yahoo.com/rss/oceania"
+ query: "doc($src)/rss/channel/item"
+ Role { name: "title"; query: "title/string()" }
+ Role { name: "link"; query: "link/string()" }
+ Role { name: "description"; query: "description/string()"; isCData: true }
+ }
+ \endqml
+ \note The model is currently static, so the above is really just a snapshot of an RSS feed.
+*/
+
+QmlXmlListModel::QmlXmlListModel(QObject *parent)
+ : QListModelInterface(*(new QmlXmlListModelPrivate), parent)
+{
+ Q_D(QmlXmlListModel);
+ connect(&d->qmlXmlQuery, SIGNAL(queryCompleted(int,int)),
+ this, SLOT(queryCompleted(int,int)));
+}
+
+QmlXmlListModel::~QmlXmlListModel()
+{
+}
+
+QmlList<XmlListModelRole *> *QmlXmlListModel::roleObjects()
+{
+ Q_D(QmlXmlListModel);
+ return &d->roleObjects;
+}
+
+QHash<int,QVariant> QmlXmlListModel::data(int index, const QList<int> &roles) const
+{
+ Q_D(const QmlXmlListModel);
+ QHash<int, QVariant> rv;
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ int roleIndex = d->roles.indexOf(role);
+ rv.insert(role, d->data.at(index).at(roleIndex));
+ }
+ return rv;
+}
+
+int QmlXmlListModel::count() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->size;
+}
+
+QList<int> QmlXmlListModel::roles() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->roles;
+}
+
+QString QmlXmlListModel::toString(int role) const
+{
+ Q_D(const QmlXmlListModel);
+ int index = d->roles.indexOf(role);
+ if (index == -1)
+ return QString();
+ return d->roleNames.at(index);
+}
+
+QString QmlXmlListModel::source() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->src;
+}
+
+void QmlXmlListModel::setSource(const QString &src)
+{
+ Q_D(QmlXmlListModel);
+ if (d->src != src) {
+ d->src = src;
+ reload();
+ }
+}
+
+QString QmlXmlListModel::query() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->query;
+}
+
+void QmlXmlListModel::setQuery(const QString &query)
+{
+ Q_D(QmlXmlListModel);
+ if (d->query != query) {
+ d->query = query;
+ reload();
+ }
+}
+
+QString QmlXmlListModel::namespaceDeclarations() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->namespaces;
+}
+
+void QmlXmlListModel::setNamespaceDeclarations(const QString &declarations)
+{
+ Q_D(QmlXmlListModel);
+ if (d->namespaces != declarations) {
+ d->namespaces = declarations;
+ reload();
+ }
+}
+QmlXmlListModel::Status QmlXmlListModel::status() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->status;
+}
+
+qreal QmlXmlListModel::progress() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->progress;
+}
+
+void QmlXmlListModel::classComplete()
+{
+ Q_D(QmlXmlListModel);
+ d->isClassComplete = true;
+ reload();
+}
+
+void QmlXmlListModel::reload()
+{
+ Q_D(QmlXmlListModel);
+
+ if (!d->isClassComplete)
+ return;
+
+ d->qmlXmlQuery.abort();
+ d->queryId = -1;
+
+ //clear existing data
+ d->size = 0;
+ int count = d->data.count();
+ d->data.clear();
+ if (count > 0)
+ emit itemsRemoved(0, count);
+
+ if (d->src.isEmpty()) {
+ qWarning() << "Can't load empty src string";
+ return;
+ }
+
+ if (d->reply) {
+ d->reply->abort();
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+ d->progress = 0.0;
+ d->status = Loading;
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+
+ QNetworkRequest req((QUrl(d->src)));
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished()));
+ QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+}
+
+void QmlXmlListModel::requestFinished()
+{
+ Q_D(QmlXmlListModel);
+ if (d->reply->error() != QNetworkReply::NoError) {
+ d->reply->deleteLater();
+ d->reply = 0;
+ d->status = Error;
+ } else {
+ d->status = Idle;
+ QByteArray data = d->reply->readAll();
+ d->queryId = d->qmlXmlQuery.doQuery(d->query, d->namespaces, data, &d->roleObjects);
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+}
+
+void QmlXmlListModel::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QmlXmlListModel);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
+
+void QmlXmlListModel::queryCompleted(int id, int size)
+{
+ Q_D(QmlXmlListModel);
+ if (id != d->queryId)
+ return;
+ d->size = size;
+ if (size > 0) {
+ d->data = d->qmlXmlQuery.modelData();
+ emit itemsInserted(0, d->size);
+ }
+}
+
+#include "qmlxmllistmodel.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlxmllistmodel.h b/src/declarative/extra/qmlxmllistmodel.h
new file mode 100644
index 0000000..052a0c2
--- /dev/null
+++ b/src/declarative/extra/qmlxmllistmodel.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLXMLLISTMODEL_H
+#define QMLXMLLISTMODEL_H
+
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/QListModelInterface>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlContext;
+class Q_DECLARATIVE_EXPORT XmlListModelRole : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(bool isCData READ isCData WRITE setIsCData)
+ Q_PROPERTY(bool isStringList READ isStringList WRITE setIsStringList)
+
+public:
+ XmlListModelRole() : m_isList(false), m_isCData(false) {}
+ ~XmlListModelRole() {}
+
+ QString name() const { return m_name; }
+ void setName(const QString &name) { m_name = name; }
+
+ QString query() const { return m_query; }
+ void setQuery(const QString &query) { m_query = query; }
+
+ bool isStringList() const { return m_isList; }
+ void setIsStringList(bool b) { m_isList = b; }
+
+ bool isCData() const { return m_isCData; }
+ void setIsCData(bool b) { m_isCData = b; }
+
+private:
+ QString m_name;
+ QString m_query;
+ bool m_isList;
+ bool m_isCData;
+};
+QML_DECLARE_TYPE(XmlListModelRole)
+
+class QmlXmlListModelPrivate;
+class Q_DECLARATIVE_EXPORT QmlXmlListModel : public QListModelInterface, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(QString source READ source WRITE setSource)
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(QString namespaceDeclarations READ namespaceDeclarations WRITE setNamespaceDeclarations)
+ Q_PROPERTY(QmlList<XmlListModelRole *> *roles READ roleObjects)
+ Q_CLASSINFO("DefaultProperty", "roles")
+public:
+ QmlXmlListModel(QObject *parent = 0);
+ ~QmlXmlListModel();
+
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual int count() const;
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+
+ QmlList<XmlListModelRole *> *roleObjects();
+
+ QString source() const;
+ void setSource(const QString&);
+
+ QString query() const;
+ void setQuery(const QString&);
+
+ QString namespaceDeclarations() const;
+ void setNamespaceDeclarations(const QString&);
+
+ enum Status { Idle, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ virtual void classComplete();
+
+signals:
+ void statusChanged(Status);
+ void progressChanged(qreal progress);
+
+public Q_SLOTS:
+ void reload();
+
+private Q_SLOTS:
+ void requestFinished();
+ void requestProgress(qint64,qint64);
+ void queryCompleted(int,int);
+
+private:
+ Q_DECLARE_PRIVATE(QmlXmlListModel)
+ Q_DISABLE_COPY(QmlXmlListModel)
+};
+
+QML_DECLARE_TYPE(QmlXmlListModel)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLXMLLISTMODEL_H
diff --git a/src/declarative/extra/qnumberformat.cpp b/src/declarative/extra/qnumberformat.cpp
new file mode 100644
index 0000000..424c125
--- /dev/null
+++ b/src/declarative/extra/qnumberformat.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnumberformat.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QNumberFormat,NumberFormat)
+
+QNumberFormat::QNumberFormat(QObject *parent) : QObject(parent), _number(0), _type(Decimal),
+ _groupingSize(0)
+{
+ _locale = QLocale::system();
+ _groupingSeparator = _locale.groupSeparator();
+ _decimalSeparator = _locale.decimalPoint();
+ _currencySymbol = QLatin1Char('$');
+}
+
+QNumberFormat::~QNumberFormat()
+{
+
+}
+
+void QNumberFormat::updateText()
+{
+ QTime t;
+ t.start();
+ static int totalTime;
+
+ handleFormat();
+
+ totalTime += t.elapsed();
+ emit textChanged();
+}
+
+void QNumberFormat::handleFormat()
+{
+ // ### is extremely messy
+ if (_format.isEmpty()) {
+ _text = QString(QLatin1String("%1")).arg(_number, -1, 'f', -1);
+ return;
+ }
+
+ QString inputString;
+
+ // ### possible to use the following parsed data in the future
+
+ int remainingLength = _format.size();
+ int currentIndex = _format.size()-1;
+
+ int maxDigits = 0;
+ int minDigits = 0;
+ int decimalLength = 0;
+
+ while (remainingLength > 0) {
+ switch(_format.at(currentIndex).unicode()) {
+ case ',':
+ if (decimalLength && !_groupingSize)
+ setGroupingSize(maxDigits - decimalLength);
+ else if (!_groupingSize)
+ setGroupingSize(maxDigits);
+ break;
+ case '.':
+ if (!decimalLength)
+ decimalLength = maxDigits;
+ break;
+ case '0':
+ minDigits++;
+ case '#':
+ maxDigits++;
+ break;
+ default:
+ break;
+ }
+ currentIndex--;
+ remainingLength--;
+ }
+
+ // round given the decimal length/precision
+ inputString = QString(QLatin1String("%1")).arg(_number, -1, 'f', decimalLength);
+
+ QStringList parts = inputString.split(QLatin1Char('.'));
+ QStringList formatParts = _format.split(QLatin1Char('.'));
+
+ if (formatParts.size() > 2 || parts.size() > 2 )
+ return;
+
+ QString formatInt = formatParts.at(0);
+
+ QString formatDec;
+ if (formatParts.size() == 2)
+ formatDec = formatParts.at(1);
+
+ QString integer = parts.at(0);
+
+ QString decimal;
+ if (parts.size() == 2)
+ decimal = parts.at(1);
+
+ QString outputDecimal = formatDecimal(formatDec, decimal);
+ QString outputInteger = formatInteger(formatInt, integer);
+
+ // insert separators
+ if (_groupingSize) {
+ unsigned int count = 0;
+ for (int i = outputInteger.size()-1; i > 0; i--) {
+ if (outputInteger.at(i).digitValue() >= 0) {
+ if (count == _groupingSize - 1) {
+ count = 0;
+ outputInteger.insert(i, _groupingSeparator);
+ }
+ else
+ count++;
+ }
+ }
+ }
+ if (!outputDecimal.isEmpty())
+ _text = outputInteger + _decimalSeparator + outputDecimal;
+ else
+ _text = outputInteger;
+}
+
+QString QNumberFormat::formatInteger(const QString &formatInt, const QString &integer)
+{
+ if (formatInt.isEmpty() || integer.isEmpty())
+ return QString();
+
+ QString outputInteger;
+ int formatIndex = formatInt.size()-1;
+
+ //easier for carry?
+ for (int index= integer.size()-1; index >= 0; index--) {
+ if (formatIndex < 0) {
+ outputInteger.push_front(integer.at(index));
+ }
+ else {
+ switch(formatInt.at(formatIndex).unicode()) {
+ case '0':
+ if (index > integer.size()-1) {
+ outputInteger.push_front(QLatin1Char('0'));
+ break;
+ }
+ case '#':
+ outputInteger.push_front(integer.at(index));
+ break;
+ case ',':
+ index++;
+ break;
+ default:
+ outputInteger.push_front(formatInt.at(formatIndex));
+ index++;
+ break;
+ }
+ formatIndex--;
+ }
+ }
+ while (formatIndex >= 0) {
+ if (formatInt.at(formatIndex).unicode() != '#' && formatInt.at(formatIndex).unicode() != ',')
+ outputInteger.push_front(formatInt.at(formatIndex));
+ formatIndex--;
+ }
+ return outputInteger;
+}
+
+QString QNumberFormat::formatDecimal(const QString &formatDec, const QString &decimal)
+{
+ QString outputDecimal;
+
+ // up to max 6 decimal places
+ for (int index=formatDec.size()-1; index >= 0; index--) {
+ switch(formatDec.at(index).unicode()) {
+ case '0':
+ outputDecimal.push_front(decimal.at(index));
+ break;
+ case '#':
+ if (decimal.at(index) != QLatin1Char('0') || outputDecimal.size() > 0)
+ outputDecimal.push_front(decimal.at(index));
+ break;
+ default:
+ outputDecimal.push_front(formatDec.at(index));
+ break;
+ }
+ }
+ return outputDecimal;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qnumberformat.h b/src/declarative/extra/qnumberformat.h
new file mode 100644
index 0000000..fba9872
--- /dev/null
+++ b/src/declarative/extra/qnumberformat.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NUMBERFORMAT_H
+#define NUMBERFORMAT_H
+
+#include <QtDeclarative/qml.h>
+#include <QtCore/QLocale>
+#include <QtCore/QTime>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+// TODO
+// be able to set Locale, instead of default system for dynamic formatting
+// add currency support
+// add additional syntax, extend to format scientific, percentiles, significant digits etc
+
+
+class QNumberFormat : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(NumberType)
+public:
+ QNumberFormat(QObject *parent=0);
+ ~QNumberFormat();
+
+ enum NumberType {
+ Percent,
+ Scientific,
+ Currency,
+ Decimal
+ };
+
+ //external property, only visible
+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
+
+ //mutatable properties to modify the output (text)
+ Q_PROPERTY(qreal number READ number WRITE setNumber)
+ Q_PROPERTY(QString format READ format WRITE setFormat)
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale)
+
+ //Format specific settings
+ Q_PROPERTY(unsigned short groupingSeparator READ groupingSeparator WRITE setGroupingSeparator)
+ Q_PROPERTY(unsigned short decimalSeperator READ decimalSeparator WRITE setDecimalSeparator)
+ Q_PROPERTY(unsigned int groupingSize READ groupingSize WRITE setGroupingSize)
+ Q_PROPERTY(unsigned short currencySymbol READ currencySymbol WRITE setCurrencySymbol)
+
+
+ QString text() const { return _text; }
+
+ qreal number() const { return _number; }
+ void setNumber(qreal n) {
+ if (_number == n)
+ return;
+ _number = n;
+ updateText();
+ }
+
+ QString format() const { return _format; }
+ void setFormat(const QString &format) {
+ if (format.isEmpty())
+ _format = QString::null;
+ else if (_format == format)
+ return;
+
+ _format = format;
+ updateText();
+ }
+
+ QLocale locale() const { return _locale; }
+ void setLocale(const QLocale &locale) { _locale = locale; updateText(); }
+
+ //Do we deal with unicode standard? or create our own
+ // ### since this is the backend for the number conversions, we will use the unicode
+ // the front-end will handle the QChar/QString -> short int
+
+ unsigned short groupingSeparator() { return _groupingSeparator.unicode(); }
+ void setGroupingSeparator(unsigned short unicodeSymbol)
+ {
+ _groupingSeparator = QChar(unicodeSymbol);
+ }
+
+ unsigned short decimalSeparator() { return _decimalSeparator.unicode(); }
+ void setDecimalSeparator(unsigned short unicodeSymbol)
+ {
+ _decimalSeparator = QChar(unicodeSymbol);
+ }
+
+ unsigned short currencySymbol() { return _currencySymbol.unicode(); }
+ void setCurrencySymbol(unsigned short unicodeSymbol)
+ {
+ _currencySymbol = QChar(unicodeSymbol);
+ }
+
+ unsigned int groupingSize() { return _groupingSize; }
+ void setGroupingSize(unsigned int size)
+ {
+ _groupingSize = size;
+ }
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ void updateText();
+ void handleFormat();
+ QString formatInteger(const QString &formatInt, const QString &integer);
+ QString formatDecimal(const QString &formatDec, const QString &decimal);
+
+ qreal _number;
+ NumberType _type;
+ QChar _groupingSeparator;
+ QChar _decimalSeparator;
+ QChar _currencySymbol;
+ unsigned int _groupingSize;
+
+ QLocale _locale;
+ QString _format;
+
+ // only hooked member at the moment
+ QString _text;
+
+};
+QML_DECLARE_TYPE(QNumberFormat)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/fx.pri b/src/declarative/fx/fx.pri
new file mode 100644
index 0000000..90820fa
--- /dev/null
+++ b/src/declarative/fx/fx.pri
@@ -0,0 +1,95 @@
+HEADERS += \
+ fx/qfxanchors.h \
+ fx/qfxanchors_p.h \
+ fx/qfxanimatedimageitem.h \
+ fx/qfxblendedimage.h \
+ fx/qfxblurfilter.h \
+ fx/qfxcomponentinstance.h \
+ fx/qfxcomponentinstance_p.h \
+ fx/qfxcontentwrapper.h \
+ fx/qfxcontentwrapper_p.h \
+ fx/qfxevents_p.h \
+ fx/qfxflickable.h \
+ fx/qfxflickable_p.h \
+ fx/qfxflipable.h \
+ fx/qfxfocuspanel.h \
+ fx/qfxfocusrealm.h \
+ fx/qfxgridview.h \
+ fx/qfxhighlightfilter.h \
+ fx/qfximage.h \
+ fx/qfxpainteditem.h \
+ fx/qfxpainteditem_p.h \
+ fx/qfximage_p.h \
+ fx/qfxitem.h \
+ fx/qfxitem_p.h \
+ fx/qfxkeyactions.h \
+ fx/qfxkeyproxy.h \
+ fx/qfxlayouts.h \
+ fx/qfxlayouts_p.h \
+ fx/qfxmouseregion.h \
+ fx/qfxmouseregion_p.h \
+ fx/qfxparticles.h \
+ fx/qfxpath.h \
+ fx/qfxpath_p.h \
+ fx/qfxpathview.h \
+ fx/qfxpathview_p.h \
+ fx/qfxrect.h \
+ fx/qfxrect_p.h \
+ fx/qfxreflectionfilter.h \
+ fx/qfxrepeater.h \
+ fx/qfxrepeater_p.h \
+ fx/qfxscalegrid.h \
+ fx/qfxshadowfilter.h \
+ fx/qfxtextedit.h \
+ fx/qfxtextedit_p.h \
+ fx/qfxtext.h \
+ fx/qfxtext_p.h \
+ fx/qfxtransform.h \
+ fx/qfxpixmap.cpp \
+ fx/qfxvisualitemmodel.h \
+ fx/qfxlistview.h \
+ fx/qfxwidgetcontainer.h \
+
+SOURCES += \
+ fx/qfxanchors.cpp \
+ fx/qfxanimatedimageitem.cpp \
+ fx/qfxblendedimage.cpp \
+ fx/qfxblurfilter.cpp \
+ fx/qfxcomponentinstance.cpp \
+ fx/qfxcontentwrapper.cpp \
+ fx/qfxevents.cpp \
+ fx/qfxflickable.cpp \
+ fx/qfxflipable.cpp \
+ fx/qfxfocuspanel.cpp \
+ fx/qfxfocusrealm.cpp \
+ fx/qfxgridview.cpp \
+ fx/qfxhighlightfilter.cpp \
+ fx/qfximage.cpp \
+ fx/qfxpainteditem.cpp \
+ fx/qfxitem.cpp \
+ fx/qfxkeyactions.cpp \
+ fx/qfxkeyproxy.cpp \
+ fx/qfxlayouts.cpp \
+ fx/qfxmouseregion.cpp \
+ fx/qfxparticles.cpp \
+ fx/qfxpath.cpp \
+ fx/qfxpathview.cpp \
+ fx/qfxrect.cpp \
+ fx/qfxreflectionfilter.cpp \
+ fx/qfxrepeater.cpp \
+ fx/qfxscalegrid.cpp \
+ fx/qfxshadowfilter.cpp \
+ fx/qfxtext.cpp \
+ fx/qfxtextedit.cpp \
+ fx/qfxtransform.cpp \
+ fx/qfxpixmap.cpp \
+ fx/qfxvisualitemmodel.cpp \
+ fx/qfxlistview.cpp \
+ fx/qfxwidgetcontainer.cpp \
+
+contains(QT_CONFIG, webkit) {
+ QT+=webkit
+ SOURCES += fx/qfxwebview.cpp
+ HEADERS += fx/qfxwebview.h
+}
+
diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp
new file mode 100644
index 0000000..bd5520a
--- /dev/null
+++ b/src/declarative/fx/qfxanchors.cpp
@@ -0,0 +1,889 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxanchors_p.h"
+#include "qfxitem.h"
+#include "qfxitem_p.h"
+#include <QDebug>
+#include <QtDeclarative/qmlinfo.h>
+#include <QtDeclarative/qmlbindablevalue.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(QFxAnchors,Anchors)
+
+//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
+//TODO: baseline support
+//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
+
+//### const item?
+//local position
+static qreal position(QFxItem *item, QFxAnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ switch(anchorLine) {
+ case QFxAnchorLine::Left:
+ ret = item->x();
+ break;
+ case QFxAnchorLine::Right:
+ ret = item->x() + item->width();
+ break;
+ case QFxAnchorLine::Top:
+ ret = item->y();
+ break;
+ case QFxAnchorLine::Bottom:
+ ret = item->y() + item->height();
+ break;
+ case QFxAnchorLine::HCenter:
+ ret = item->x() + item->width()/2;
+ break;
+ case QFxAnchorLine::VCenter:
+ ret = item->y() + item->height()/2;
+ break;
+ case QFxAnchorLine::Baseline:
+ ret = item->y() + item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+//position when origin is 0,0
+static qreal adjustedPosition(QFxItem *item, QFxAnchorLine::AnchorLine anchorLine)
+{
+ int ret = 0;
+ switch(anchorLine) {
+ case QFxAnchorLine::Left:
+ ret = 0;
+ break;
+ case QFxAnchorLine::Right:
+ ret = item->width();
+ break;
+ case QFxAnchorLine::Top:
+ ret = 0;
+ break;
+ case QFxAnchorLine::Bottom:
+ ret = item->height();
+ break;
+ case QFxAnchorLine::HCenter:
+ ret = item->width()/2;
+ break;
+ case QFxAnchorLine::VCenter:
+ ret = item->height()/2;
+ break;
+ case QFxAnchorLine::Baseline:
+ ret = item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ \internal
+ \class QFxAnchors
+ \ingroup group_layouts
+ \brief The QFxAnchors class provides a way to lay out items relative to other items.
+
+ \warning Currently, only anchoring to siblings or parent is supported.
+*/
+
+QFxAnchors::QFxAnchors(QObject *parent)
+ : QObject(*new QFxAnchorsPrivate(), parent)
+{
+}
+
+QFxAnchors::~QFxAnchors()
+{
+ Q_D(QFxAnchors);
+ d->remDepend(d->fill);
+ d->remDepend(d->centeredIn);
+ d->remDepend(d->left.item);
+ d->remDepend(d->right.item);
+ d->remDepend(d->top.item);
+ d->remDepend(d->bottom.item);
+ d->remDepend(d->vCenter.item);
+ d->remDepend(d->hCenter.item);
+ d->remDepend(d->baseline.item);
+}
+
+void QFxAnchorsPrivate::fillChanged()
+{
+ if (!fill || !isItemComplete())
+ return;
+
+ if (fill == item->itemParent()) { //child-parent
+ setItemPos(QPointF(leftMargin, topMargin));
+ } else if (fill->itemParent() == item->itemParent()) { //siblings
+ setItemPos(QPointF(fill->x()+leftMargin, fill->y()+topMargin));
+ }
+ setItemWidth(fill->width()-leftMargin-rightMargin);
+ setItemHeight(fill->height()-topMargin-bottomMargin);
+}
+
+void QFxAnchorsPrivate::centeredInChanged()
+{
+ if (!centeredIn || fill || !isItemComplete())
+ return;
+
+ if (centeredIn == item->itemParent()) {
+ QPointF p((item->itemParent()->width() - item->width()) / 2.,
+ (item->itemParent()->height() - item->height()) / 2.);
+ setItemPos(p);
+
+ } else if (centeredIn->itemParent() == item->itemParent()) {
+
+ QPointF p(centeredIn->x() + (centeredIn->width() - item->width()) / 2.,
+ centeredIn->y() + (centeredIn->height() - item->height()) / 2.);
+ setItemPos(p);
+ }
+}
+
+void QFxAnchorsPrivate::clearItem(QFxItem *item)
+{
+ if (fill == item)
+ fill = 0;
+ if (centeredIn == item)
+ centeredIn = 0;
+ if (left.item == item) {
+ left.item = 0;
+ usedAnchors &= ~QFxAnchors::HasLeftAnchor;
+ }
+ if (right.item == item) {
+ right.item = 0;
+ usedAnchors &= ~QFxAnchors::HasRightAnchor;
+ }
+ if (top.item == item) {
+ top.item = 0;
+ usedAnchors &= ~QFxAnchors::HasTopAnchor;
+ }
+ if (bottom.item == item) {
+ bottom.item = 0;
+ usedAnchors &= ~QFxAnchors::HasBottomAnchor;
+ }
+ if (vCenter.item == item) {
+ vCenter.item = 0;
+ usedAnchors &= ~QFxAnchors::HasVCenterAnchor;
+ }
+ if (hCenter.item == item) {
+ hCenter.item = 0;
+ usedAnchors &= ~QFxAnchors::HasHCenterAnchor;
+ }
+ if (baseline.item == item) {
+ baseline.item = 0;
+ usedAnchors &= ~QFxAnchors::HasBaselineAnchor;
+ }
+}
+
+void QFxAnchorsPrivate::addDepend(QFxItem *item)
+{
+ Q_Q(QFxAnchors);
+ if (!item)
+ return;
+ QFxItemPrivate *p =
+ static_cast<QFxItemPrivate *>(QObjectPrivate::get(item));
+ p->dependantAnchors.append(q);
+}
+
+void QFxAnchorsPrivate::remDepend(QFxItem *item)
+{
+ Q_Q(QFxAnchors);
+ if (!item)
+ return;
+ QFxItemPrivate *p =
+ static_cast<QFxItemPrivate *>(QObjectPrivate::get(item));
+ p->dependantAnchors.removeAll(q);
+}
+
+bool QFxAnchorsPrivate::isItemComplete() const
+{
+ return item->isComponentComplete();
+}
+
+void QFxAnchorsPrivate::setItemHeight(qreal v)
+{
+ updatingMe = true;
+ item->setHeight(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemWidth(qreal v)
+{
+ updatingMe = true;
+ item->setWidth(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemX(qreal v)
+{
+ updatingMe = true;
+ item->setX(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemY(qreal v)
+{
+ updatingMe = true;
+ item->setY(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemPos(const QPointF &v)
+{
+ updatingMe = true;
+ item->setPos(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::updateMe()
+{
+ if (updatingMe) {
+ updatingMe = false;
+ return;
+ }
+
+ fillChanged();
+ centeredInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QFxAnchorsPrivate::updateOnComplete()
+{
+ fillChanged();
+ centeredInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QFxAnchorsPrivate::update(QFxItem *, const QRectF &newG, const QRectF &oldG)
+{
+ fillChanged();
+ centeredInChanged();
+
+ if (newG.x() != oldG.x() || newG.width() != oldG.width())
+ updateHorizontalAnchors();
+ if (newG.y() != oldG.y() || newG.height() != oldG.height())
+ updateVerticalAnchors();
+}
+
+/*!
+ \property QFxAnchors::fill
+ \brief which item the item should fill.
+
+ This is a convenience property. It is the same as anchoring the left, right, top, and bottom
+ to another item's left, right, top, and bottom.
+*/
+QFxItem *QFxAnchors::fill() const
+{
+ Q_D(const QFxAnchors);
+ return d->fill;
+}
+
+void QFxAnchors::setFill(QFxItem *f)
+{
+ Q_D(QFxAnchors);
+ d->remDepend(d->fill);
+ d->fill = f;
+ d->addDepend(d->fill);
+
+ d->fillChanged();
+}
+
+/*!
+ \property QFxAnchors::centeredIn
+ \brief which item the item should stay centered in.
+
+ This is a convenience property. It is the same as anchoring the horizontalCenter
+ and verticalCenter to another item's horizontalCenter and verticalCenter.
+*/
+QFxItem *QFxAnchors::centeredIn() const
+{
+ Q_D(const QFxAnchors);
+ return d->centeredIn;
+}
+
+void QFxAnchors::setCenteredIn(QFxItem* c)
+{
+ Q_D(QFxAnchors);
+ if (!c){
+ qmlInfo(d->item) << "Cannot center in null item.";
+ return;
+ }
+ if (c != d->item->itemParent() && c->itemParent() != d->item->itemParent()){
+ qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling.";
+ return;
+ }
+
+ d->remDepend(d->centeredIn);
+ d->centeredIn = c;
+ d->addDepend(d->centeredIn);
+
+ d->centeredInChanged();
+}
+
+bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1,
+ const QFxAnchorLine &edge2,
+ int offset1,
+ int offset2,
+ QFxAnchorLine::AnchorLine line,
+ int &stretch)
+{
+ bool edge1IsParent = (edge1.item == item->itemParent());
+ bool edge2IsParent = (edge2.item == item->itemParent());
+ bool edge1IsSibling = (edge1.item->itemParent() == item->itemParent());
+ bool edge2IsSibling = (edge2.item->itemParent() == item->itemParent());
+
+ bool invalid = false;
+ if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsParent && edge1IsSibling) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(item->itemParent(), line)
+ + (int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsSibling && edge1IsParent) {
+ stretch = ((int)position(item->itemParent(), line) + (int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else
+ invalid = true;
+
+ return invalid;
+}
+
+void QFxAnchorsPrivate::updateVerticalAnchors()
+{
+ if (fill || centeredIn || !isItemComplete())
+ return;
+
+ if (!updatingVerticalAnchor) {
+ updatingVerticalAnchor = true;
+ if (usedAnchors & QFxAnchors::HasTopAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ int height = 0;
+ if (usedAnchors & QFxAnchors::HasBottomAnchor) {
+ invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QFxAnchorLine::Top, height);
+ } else if (usedAnchors & QFxAnchors::HasVCenterAnchor) {
+ invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QFxAnchorLine::Top, height);
+ height *= 2;
+ }
+ if (!invalid)
+ setItemHeight(height);
+
+ //Handle top
+ if (top.item == item->itemParent()) {
+ setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
+ } else if (top.item->itemParent() == item->itemParent()) {
+ setItemY(position(top.item, top.anchorLine) + topMargin);
+ }
+ } else if (usedAnchors & QFxAnchors::HasBottomAnchor) {
+ //Handle stretching (top + bottom case is handled above)
+ if (usedAnchors & QFxAnchors::HasVCenterAnchor) {
+ int height = 0;
+ bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
+ QFxAnchorLine::Top, height);
+ if (!invalid)
+ setItemHeight(height*2);
+ }
+
+ //Handle bottom
+ if (bottom.item == item->itemParent()) {
+ setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
+ } else if (bottom.item->itemParent() == item->itemParent()) {
+ setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
+ }
+ } else if (usedAnchors & QFxAnchors::HasVCenterAnchor) {
+ //(stetching handled above)
+
+ //Handle vCenter
+ if (vCenter.item == item->itemParent()) {
+ setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
+ - item->height()/2 + vCenterOffset);
+ } else if (vCenter.item->itemParent() == item->itemParent()) {
+ setItemY(position(vCenter.item, vCenter.anchorLine) - item->height()/2 + vCenterOffset);
+ }
+ } else if (usedAnchors & QFxAnchors::HasBaselineAnchor) {
+ //Handle baseline
+ if (baseline.item->itemParent() == item->itemParent()) {
+ setItemY(position(baseline.item, baseline.anchorLine) - item->baselineOffset());
+ }
+ }
+ updatingVerticalAnchor = false;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << "Possible anchor loop detected on vertical anchor.";
+ }
+}
+
+void QFxAnchorsPrivate::updateHorizontalAnchors()
+{
+ if (fill || centeredIn || !isItemComplete())
+ return;
+
+ if (!updatingHorizontalAnchor) {
+ updatingHorizontalAnchor = true;
+
+ if (usedAnchors & QFxAnchors::HasLeftAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ int width = 0;
+ if (usedAnchors & QFxAnchors::HasRightAnchor) {
+ invalid = calcStretch(left, right, leftMargin, -rightMargin, QFxAnchorLine::Left, width);
+ } else if (usedAnchors & QFxAnchors::HasHCenterAnchor) {
+ invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QFxAnchorLine::Left, width);
+ width *= 2;
+ }
+ if (!invalid)
+ setItemWidth(width);
+
+ //Handle left
+ if (left.item == item->itemParent()) {
+ setItemX(adjustedPosition(left.item, left.anchorLine) + leftMargin);
+ } else if (left.item->itemParent() == item->itemParent()) {
+ setItemX(position(left.item, left.anchorLine) + leftMargin);
+ }
+ } else if (usedAnchors & QFxAnchors::HasRightAnchor) {
+ //Handle stretching (left + right case is handled in updateLeftAnchor)
+ if (usedAnchors & QFxAnchors::HasHCenterAnchor) {
+ int width = 0;
+ bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin,
+ QFxAnchorLine::Left, width);
+ if (!invalid)
+ setItemWidth(width*2);
+ }
+
+ //Handle right
+ if (right.item == item->itemParent()) {
+ setItemX(adjustedPosition(right.item, right.anchorLine) - item->width() - rightMargin);
+ } else if (right.item->itemParent() == item->itemParent()) {
+ setItemX(position(right.item, right.anchorLine) - item->width() - rightMargin);
+ }
+ } else if (usedAnchors & QFxAnchors::HasHCenterAnchor) {
+ //Handle hCenter
+ if (hCenter.item == item->itemParent()) {
+ setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset);
+ } else if (hCenter.item->itemParent() == item->itemParent()) {
+ setItemX(position(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset);
+ }
+ }
+
+ updatingHorizontalAnchor = false;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << "Possible anchor loop detected on horizontal anchor.";
+ }
+}
+
+QFxAnchorLine QFxAnchors::top() const
+{
+ Q_D(const QFxAnchors);
+ return d->top;
+}
+
+void QFxAnchors::setTop(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ if (edge.item)
+ d->usedAnchors |= HasTopAnchor;
+ else
+ d->usedAnchors &= ~HasTopAnchor;
+
+ d->checkVValid();
+
+ d->remDepend(d->top.item);
+ d->top = edge;
+ d->addDepend(d->top.item);
+ d->updateVerticalAnchors();
+}
+
+void QFxAnchors::resetTop()
+{
+ setTop(QFxAnchorLine());
+}
+
+QFxAnchorLine QFxAnchors::bottom() const
+{
+ Q_D(const QFxAnchors);
+ return d->bottom;
+}
+
+void QFxAnchors::setBottom(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ if (edge.item)
+ d->usedAnchors |= HasBottomAnchor;
+ else
+ d->usedAnchors &= ~HasBottomAnchor;
+
+ d->checkVValid();
+
+ d->remDepend(d->bottom.item);
+ d->bottom = edge;
+ d->addDepend(d->bottom.item);
+ d->updateVerticalAnchors();
+}
+
+void QFxAnchors::resetBottom()
+{
+ setBottom(QFxAnchorLine());
+}
+
+QFxAnchorLine QFxAnchors::verticalCenter() const
+{
+ Q_D(const QFxAnchors);
+ return d->vCenter;
+}
+
+void QFxAnchors::setVerticalCenter(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ if (edge.item)
+ d->usedAnchors |= HasVCenterAnchor;
+ else
+ d->usedAnchors &= ~HasVCenterAnchor;
+
+ d->checkVValid();
+
+ d->remDepend(d->vCenter.item);
+ d->vCenter = edge;
+ d->addDepend(d->vCenter.item);
+ d->updateVerticalAnchors();
+}
+
+void QFxAnchors::resetVerticalCenter()
+{
+ setVerticalCenter(QFxAnchorLine());
+}
+
+QFxAnchorLine QFxAnchors::baseline() const
+{
+ Q_D(const QFxAnchors);
+ return d->baseline;
+}
+
+void QFxAnchors::setBaseline(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ if (edge.item)
+ d->usedAnchors |= HasBaselineAnchor;
+ else
+ d->usedAnchors &= ~HasBaselineAnchor;
+
+ d->checkVValid();
+
+ d->remDepend(d->baseline.item);
+ d->baseline = edge;
+ d->addDepend(d->baseline.item);
+ d->updateVerticalAnchors();
+}
+
+void QFxAnchors::resetBaseline()
+{
+ setBaseline(QFxAnchorLine());
+}
+
+QFxAnchorLine QFxAnchors::left() const
+{
+ Q_D(const QFxAnchors);
+ return d->left;
+}
+
+void QFxAnchors::setLeft(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ if (edge.item)
+ d->usedAnchors |= HasLeftAnchor;
+ else
+ d->usedAnchors &= ~HasLeftAnchor;
+
+ d->checkHValid();
+
+ d->remDepend(d->left.item);
+ d->left = edge;
+ d->addDepend(d->left.item);
+ d->updateHorizontalAnchors();
+}
+
+void QFxAnchors::resetLeft()
+{
+ setLeft(QFxAnchorLine());
+}
+
+QFxAnchorLine QFxAnchors::right() const
+{
+ Q_D(const QFxAnchors);
+ return d->right;
+}
+
+void QFxAnchors::setRight(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ if (edge.item)
+ d->usedAnchors |= HasRightAnchor;
+ else
+ d->usedAnchors &= ~HasRightAnchor;
+
+ d->checkHValid();
+
+ d->remDepend(d->right.item);
+ d->right = edge;
+ d->addDepend(d->right.item);
+
+ d->updateHorizontalAnchors();
+}
+
+void QFxAnchors::resetRight()
+{
+ setRight(QFxAnchorLine());
+}
+
+QFxAnchorLine QFxAnchors::horizontalCenter() const
+{
+ Q_D(const QFxAnchors);
+ return d->hCenter;
+}
+
+void QFxAnchors::setHorizontalCenter(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ if (edge.item)
+ d->usedAnchors |= HasHCenterAnchor;
+ else
+ d->usedAnchors &= ~HasHCenterAnchor;
+
+ d->checkHValid();
+
+ d->remDepend(d->hCenter.item);
+ d->hCenter = edge;
+ d->addDepend(d->hCenter.item);
+ d->updateHorizontalAnchors();
+}
+
+void QFxAnchors::resetHorizontalCenter()
+{
+ setHorizontalCenter(QFxAnchorLine());
+}
+
+int QFxAnchors::leftMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->leftMargin;
+}
+
+void QFxAnchors::setLeftMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->leftMargin == offset)
+ return;
+ d->leftMargin = offset;
+ emit leftMarginChanged();
+}
+
+int QFxAnchors::rightMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->rightMargin;
+}
+
+void QFxAnchors::setRightMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->rightMargin == offset)
+ return;
+ d->rightMargin = offset;
+ emit rightMarginChanged();
+}
+
+int QFxAnchors::horizontalCenterOffset() const
+{
+ Q_D(const QFxAnchors);
+ return d->hCenterOffset;
+}
+
+void QFxAnchors::setHorizontalCenterOffset(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->hCenterOffset == offset)
+ return;
+ d->hCenterOffset = offset;
+ emit horizontalCenterOffsetChanged();
+}
+
+int QFxAnchors::topMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->topMargin;
+}
+
+void QFxAnchors::setTopMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->topMargin == offset)
+ return;
+ d->topMargin = offset;
+ emit topMarginChanged();
+}
+
+int QFxAnchors::bottomMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->bottomMargin;
+}
+
+void QFxAnchors::setBottomMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->bottomMargin == offset)
+ return;
+ d->bottomMargin = offset;
+ emit bottomMarginChanged();
+}
+
+int QFxAnchors::verticalCenterOffset() const
+{
+ Q_D(const QFxAnchors);
+ return d->vCenterOffset;
+}
+
+void QFxAnchors::setVerticalCenterOffset(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->vCenterOffset == offset)
+ return;
+ d->vCenterOffset = offset;
+ emit verticalCenterOffsetChanged();
+}
+
+QFxAnchors::UsedAnchors QFxAnchors::usedAnchors() const
+{
+ Q_D(const QFxAnchors);
+ return d->usedAnchors;
+}
+
+void QFxAnchors::setItem(QFxItem *item)
+{
+ Q_D(QFxAnchors);
+ d->item = item;
+}
+
+bool QFxAnchorsPrivate::checkHValid() const
+{
+ if (usedAnchors & QFxAnchors::HasLeftAnchor &&
+ usedAnchors & QFxAnchors::HasRightAnchor &&
+ usedAnchors & QFxAnchors::HasHCenterAnchor) {
+ qmlInfo(item) << "Can't specify left, right, and hcenter anchors.";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkHAnchorValid(QFxAnchorLine anchor) const
+{
+ if (anchor.anchorLine & QFxAnchorLine::Vertical_Mask) {
+ qmlInfo(item) << "Can't anchor a horizontal edge to a vertical edge.";
+ return false;
+ }else if (anchor.item == item){
+ qmlInfo(item) << "Can't anchor item to self.";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkVValid() const
+{
+ if (usedAnchors & QFxAnchors::HasTopAnchor &&
+ usedAnchors & QFxAnchors::HasBottomAnchor &&
+ usedAnchors & QFxAnchors::HasVCenterAnchor) {
+ qmlInfo(item) << "Can't specify top, bottom, and vcenter anchors.";
+ return false;
+ } else if (usedAnchors & QFxAnchors::HasBaselineAnchor &&
+ (usedAnchors & QFxAnchors::HasTopAnchor ||
+ usedAnchors & QFxAnchors::HasBottomAnchor ||
+ usedAnchors & QFxAnchors::HasVCenterAnchor)) {
+ qmlInfo(item) << "Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors.";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkVAnchorValid(QFxAnchorLine anchor) const
+{
+ if (anchor.anchorLine & QFxAnchorLine::Horizontal_Mask) {
+ qmlInfo(item) << "Can't anchor a vertical edge to a horizontal edge.";
+ return false;
+ }else if (anchor.item == item){
+ qmlInfo(item) << "Can't anchor item to self.";
+ return false;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxanchors.h b/src/declarative/fx/qfxanchors.h
new file mode 100644
index 0000000..0e44223
--- /dev/null
+++ b/src/declarative/fx/qfxanchors.h
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANCHORS_H
+#define QFXANCHORS_H
+
+#include <QtCore/QObject>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxItem;
+class QFxAnchorsPrivate;
+
+class QFxAnchorLine
+{
+public:
+ QFxAnchorLine() : item(0), anchorLine(Left)
+ {
+ }
+
+ enum AnchorLine {
+ Left = 0x01,
+ Right = 0x02,
+ Top = 0x04,
+ Bottom = 0x08,
+ HCenter = 0x10,
+ VCenter = 0x20,
+ Baseline = 0x40,
+ Horizontal_Mask = Left | Right | HCenter,
+ Vertical_Mask = Top | Bottom | VCenter | Baseline
+ };
+
+ QFxItem *item;
+ AnchorLine anchorLine;
+};
+
+Q_DECLARE_METATYPE(QFxAnchorLine)
+
+class QFxAnchorsPrivate;
+class Q_DECLARATIVE_EXPORT QFxAnchors : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxAnchorLine left READ left WRITE setLeft RESET resetLeft)
+ Q_PROPERTY(QFxAnchorLine right READ right WRITE setRight RESET resetRight)
+ Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter)
+ Q_PROPERTY(QFxAnchorLine top READ top WRITE setTop RESET resetTop)
+ Q_PROPERTY(QFxAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom)
+ Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter)
+ Q_PROPERTY(QFxAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline)
+ Q_PROPERTY(int leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(int horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged())
+ Q_PROPERTY(int topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(int bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(int verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged())
+ Q_PROPERTY(QFxItem *fill READ fill WRITE setFill)
+ Q_PROPERTY(QFxItem *centeredIn READ centeredIn WRITE setCenteredIn)
+
+public:
+ QFxAnchors(QObject *parent=0);
+ virtual ~QFxAnchors();
+
+ enum UsedAnchor {
+ HasLeftAnchor = 0x01,
+ HasRightAnchor = 0x02,
+ HasTopAnchor = 0x04,
+ HasBottomAnchor = 0x08,
+ HasHCenterAnchor = 0x10,
+ HasVCenterAnchor = 0x20,
+ HasBaselineAnchor = 0x40,
+ Horizontal_Mask = HasLeftAnchor | HasRightAnchor | HasHCenterAnchor,
+ Vertical_Mask = HasTopAnchor | HasBottomAnchor | HasVCenterAnchor | HasBaselineAnchor
+ };
+ Q_DECLARE_FLAGS(UsedAnchors, UsedAnchor)
+
+ QFxAnchorLine left() const;
+ void setLeft(const QFxAnchorLine &edge);
+ Q_INVOKABLE void resetLeft(); //### temporarily invokable for testing
+
+ QFxAnchorLine right() const;
+ void setRight(const QFxAnchorLine &edge);
+ void resetRight();
+
+ QFxAnchorLine horizontalCenter() const;
+ void setHorizontalCenter(const QFxAnchorLine &edge);
+ void resetHorizontalCenter();
+
+ QFxAnchorLine top() const;
+ void setTop(const QFxAnchorLine &edge);
+ void resetTop();
+
+ QFxAnchorLine bottom() const;
+ void setBottom(const QFxAnchorLine &edge);
+ void resetBottom();
+
+ QFxAnchorLine verticalCenter() const;
+ void setVerticalCenter(const QFxAnchorLine &edge);
+ void resetVerticalCenter();
+
+ QFxAnchorLine baseline() const;
+ void setBaseline(const QFxAnchorLine &edge);
+ void resetBaseline();
+
+ int leftMargin() const;
+ void setLeftMargin(int);
+
+ int rightMargin() const;
+ void setRightMargin(int);
+
+ int horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(int);
+
+ int topMargin() const;
+ void setTopMargin(int);
+
+ int bottomMargin() const;
+ void setBottomMargin(int);
+
+ int verticalCenterOffset() const;
+ void setVerticalCenterOffset(int);
+
+ QFxItem *fill() const;
+ void setFill(QFxItem *);
+
+ QFxItem *centeredIn() const;
+ void setCenteredIn(QFxItem *);
+
+ UsedAnchors usedAnchors() const;
+
+ void setItem(QFxItem *item);
+
+Q_SIGNALS:
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+
+private:
+ friend class QFxItem;
+ Q_DISABLE_COPY(QFxAnchors)
+ Q_DECLARE_PRIVATE(QFxAnchors)
+};
+
+QML_DECLARE_TYPE(QFxAnchors)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxanchors_p.h b/src/declarative/fx/qfxanchors_p.h
new file mode 100644
index 0000000..32d8b75
--- /dev/null
+++ b/src/declarative/fx/qfxanchors_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANCHORS_P_H
+#define QFXANCHORS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxanchors.h"
+#include "private/qobject_p.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxAnchorsPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QFxAnchors)
+public:
+ QFxAnchorsPrivate()
+ : updatingMe(false), updatingHorizontalAnchor(false),
+ updatingVerticalAnchor(false), item(0), usedAnchors(0), fill(0),
+ centeredIn(0), leftMargin(0), rightMargin(0), topMargin(0),
+ bottomMargin(0), vCenterOffset(0), hCenterOffset(0)
+ {
+ }
+
+ void init()
+ {
+ }
+
+ void clearItem(QFxItem *);
+
+ void addDepend(QFxItem *);
+ void remDepend(QFxItem *);
+ bool isItemComplete() const;
+
+ bool updatingMe:1;
+ bool updatingHorizontalAnchor:1;
+ bool updatingVerticalAnchor:1;
+
+ void setItemHeight(qreal);
+ void setItemWidth(qreal);
+ void setItemX(qreal);
+ void setItemY(qreal);
+ void setItemPos(const QPointF &);
+
+ void updateOnComplete();
+ void updateMe();
+ void update(QFxItem *, const QRectF &, const QRectF &);
+
+ bool checkHValid() const;
+ bool checkVValid() const;
+ bool checkHAnchorValid(QFxAnchorLine anchor) const;
+ bool checkVAnchorValid(QFxAnchorLine anchor) const;
+ bool calcStretch(const QFxAnchorLine &edge1, const QFxAnchorLine &edge2, int offset1, int offset2, QFxAnchorLine::AnchorLine line, int &stretch);
+
+ void updateHorizontalAnchors();
+ void updateVerticalAnchors();
+ void fillChanged();
+ void centeredInChanged();
+
+ QFxItem *item;
+ QFxAnchors::UsedAnchors usedAnchors;
+
+ QFxItem *fill;
+ QFxItem *centeredIn;
+
+ QFxAnchorLine left;
+ QFxAnchorLine right;
+ QFxAnchorLine top;
+ QFxAnchorLine bottom;
+ QFxAnchorLine vCenter;
+ QFxAnchorLine hCenter;
+ QFxAnchorLine baseline;
+
+ int leftMargin;
+ int rightMargin;
+ int topMargin;
+ int bottomMargin;
+ int vCenterOffset;
+ int hCenterOffset;
+
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxanimatedimageitem.cpp b/src/declarative/fx/qfxanimatedimageitem.cpp
new file mode 100644
index 0000000..029206b
--- /dev/null
+++ b/src/declarative/fx/qfxanimatedimageitem.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QMovie>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#include "qfxanimatedimageitem.h"
+#include "qfxanimatedimageitem_p.h"
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QFxAnimatedImageItem
+ \internal
+*/
+
+/*!
+ \qmlclass AnimatedImage
+ \inherits Image
+
+ This item provides for playing animations stored as images containing a series of frames,
+ such as GIF files. The full list of supported formats can be determined with
+ QMovie::supportedFormats().
+
+ \table
+ \row
+ \o \image animatedimageitem.gif
+ \o
+ \qml
+Item {
+ width: anim.width; height: anim.height+8
+ AnimatedImage { id: anim; source: "pics/games-anim.gif" }
+ Rect { color: "red"; width: 4; height: 8; y: anim.height
+ x: (anim.width-width)*anim.currentFrame/(anim.frameCount-1)
+ }
+}
+ \endqml
+ \endtable
+*/
+QML_DEFINE_TYPE(QFxAnimatedImageItem, AnimatedImage)
+
+QFxAnimatedImageItem::QFxAnimatedImageItem(QFxItem *parent)
+ : QFxImage(*(new QFxAnimatedImageItemPrivate), parent)
+{
+}
+
+QFxAnimatedImageItem::QFxAnimatedImageItem(QFxAnimatedImageItemPrivate &dd, QFxItem *parent)
+ : QFxImage(dd, parent)
+{
+}
+
+QFxAnimatedImageItem::~QFxAnimatedImageItem()
+{
+ Q_D(QFxAnimatedImageItem);
+ delete d->_movie;
+}
+
+/*!
+ \qmlproperty bool AnimatedImage::playing
+ This property holds whether the animated image is playing or not
+
+ Defaults to true, so as to start playing immediately.
+*/
+bool QFxAnimatedImageItem::isPlaying() const
+{
+ Q_D(const QFxAnimatedImageItem);
+ if (!d->_movie)
+ return false;
+ return d->_movie->state()==QMovie::Running;
+}
+
+void QFxAnimatedImageItem::setPlaying(bool play)
+{
+ Q_D(QFxAnimatedImageItem);
+ if (!d->_movie)
+ return;
+ if (play)
+ d->_movie->start();
+ else
+ d->_movie->stop();
+}
+
+/*!
+ \qmlproperty int AnimatedImage::currentFrame
+ \qmlproperty int AnimatedImage::frameCount
+
+ currentFrame is the frame that is currently visible. Watching when this changes can
+ allow other things to animate at the same time as the image. frameCount is the number
+ of frames in the animation. For some animation formats, frameCount is unknown and set to zero.
+*/
+int QFxAnimatedImageItem::currentFrame() const
+{
+ Q_D(const QFxAnimatedImageItem);
+ if (!d->_movie)
+ return -1;
+ return d->_movie->currentFrameNumber();
+}
+
+void QFxAnimatedImageItem::setCurrentFrame(int frame)
+{
+ Q_D(QFxAnimatedImageItem);
+ if (!d->_movie)
+ return;
+ d->_movie->jumpToFrame(frame);
+}
+
+int QFxAnimatedImageItem::frameCount() const
+{
+ Q_D(const QFxAnimatedImageItem);
+ if (!d->_movie)
+ return 0;
+ return d->_movie->frameCount();
+}
+
+void QFxAnimatedImageItem::setSource(const QString &url)
+{
+ Q_D(QFxAnimatedImageItem);
+ if (url == d->source)
+ return;
+
+ delete d->_movie;
+ d->_movie = 0;
+
+ if (d->reply) {
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+
+ d->source = url;
+ d->url = qmlContext(this)->resolvedUrl(url);
+
+ if (url.isEmpty()) {
+ delete d->_movie;
+ d->status = Idle;
+ } else {
+ d->status = Loading;
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(movieRequestFinished()));
+ }
+
+ emit statusChanged(d->status);
+}
+
+void QFxAnimatedImageItem::movieRequestFinished()
+{
+ Q_D(QFxAnimatedImageItem);
+ d->_movie = new QMovie(d->reply);
+ if (!d->_movie->isValid()){
+ qWarning() << "Error Reading File " << d->url;
+ delete d->_movie;
+ d->_movie = 0;
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SIGNAL(playingChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ d->_movie->start();
+ setPixmap(d->_movie->currentPixmap());
+}
+
+void QFxAnimatedImageItem::movieUpdate()
+{
+ Q_D(QFxAnimatedImageItem);
+ setPixmap(d->_movie->currentPixmap());
+ emit frameChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxanimatedimageitem.h b/src/declarative/fx/qfxanimatedimageitem.h
new file mode 100644
index 0000000..a0d14c4
--- /dev/null
+++ b/src/declarative/fx/qfxanimatedimageitem.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANIMATEDIMAGEITEM_H
+#define QFXANIMATEDIMAGEITEM_H
+
+#include <QtDeclarative/qfximage.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QMovie;
+class QFxAnimatedImageItemPrivate;
+
+class Q_DECLARATIVE_EXPORT QFxAnimatedImageItem : public QFxImage
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
+ Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged)
+ Q_PROPERTY(int frameCount READ frameCount)
+public:
+ QFxAnimatedImageItem(QFxItem *parent=0);
+ ~QFxAnimatedImageItem();
+
+ bool isPlaying() const;
+ void setPlaying(bool play);
+
+ int currentFrame() const;
+ void setCurrentFrame(int frame);
+
+ int frameCount() const;
+
+ // Extends QFxImage's src property*/
+ virtual void setSource(const QString&);
+
+Q_SIGNALS:
+ void playingChanged();
+ void frameChanged();
+
+private Q_SLOTS:
+ void movieUpdate();
+ void movieRequestFinished();
+
+protected:
+ QFxAnimatedImageItem(QFxAnimatedImageItemPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxAnimatedImageItem)
+ Q_DECLARE_PRIVATE(QFxAnimatedImageItem)
+};
+
+QML_DECLARE_TYPE(QFxAnimatedImageItem)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxanimatedimageitem_p.h b/src/declarative/fx/qfxanimatedimageitem_p.h
new file mode 100644
index 0000000..cb5da63
--- /dev/null
+++ b/src/declarative/fx/qfxanimatedimageitem_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANIMATEDIMAGE_P_H
+#define QFXANIMATEDIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfximage_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMovie;
+
+class QFxAnimatedImageItemPrivate : public QFxImagePrivate
+{
+ Q_DECLARE_PUBLIC(QFxAnimatedImageItem)
+
+public:
+ QFxAnimatedImageItemPrivate()
+ : _movie(0)
+ {
+ }
+
+ QMovie *_movie;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXANIMATEDIMAGE_P_H
diff --git a/src/declarative/fx/qfxblendedimage.cpp b/src/declarative/fx/qfxblendedimage.cpp
new file mode 100644
index 0000000..4c6eb58
--- /dev/null
+++ b/src/declarative/fx/qfxblendedimage.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxblendedimage.h"
+#include <QtDeclarative/qmlcontext.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glbasicshaders.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass BlendedImage
+ \brief The BlendedImage elements blends two different images depending on a blend ratio.
+
+ This element can be used to simulate blur on slow devices by setting secondaryUrl with
+ a pre-rendered blurred version of primaryUrl.
+
+ Note that this class will only work under OpenGL. On the software canvas it will display
+ only the primary image unless the blend is > 0.75, in which case it will display only the
+ secondary image.
+*/
+
+/*!
+ \internal
+ \class QFxBlendedImage
+ \brief The QFxBlendedImage blends two different images depending on a blend ratio.
+
+ This class can be used to simulate blur on slow devices by setting secondaryUrl with
+ a pre-rendered blurred version of primaryUrl.
+
+ Note that this class will only work under OpenGL. On the software canvas it will display
+ only the primary image unless the blend is > 0.75, in which case it will display only the
+ secondary image.
+*/
+QFxBlendedImage::QFxBlendedImage(QFxItem *parent)
+: QFxItem(parent), _blend(0), _smooth(false), dirty(false)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ setOptions(HasContents);
+#endif
+}
+
+/*!
+ \qmlproperty string BlendedImage::primaryUrl
+ The URL of the first image to be displayed in this item.
+*/
+QString QFxBlendedImage::primaryUrl() const
+{
+ return primSrc;
+}
+
+void QFxBlendedImage::primaryLoaded()
+{
+ primPix = QFxPixmap(primUrl);
+ dirty = true;
+ update();
+}
+
+void QFxBlendedImage::setPrimaryUrl(const QString &url)
+{
+ if (primSrc == url)
+ return;
+ if (!primSrc.isEmpty())
+ QFxPixmap::cancelGet(primUrl,this);
+ primSrc = url;
+ primUrl = qmlContext(this)->resolvedUrl(url);
+ if (!primSrc.isEmpty())
+ QFxPixmap::get(qmlEngine(this), primUrl,this,SLOT(primaryLoaded()));
+}
+
+/*!
+ \qmlproperty string BlendedImage::secondaryUrl
+ The URL of the second image to be displayed in this item.
+*/
+QString QFxBlendedImage::secondaryUrl() const
+{
+ return secSrc;
+}
+
+void QFxBlendedImage::secondaryLoaded()
+{
+ secPix = QFxPixmap(secUrl);
+ dirty = true;
+ update();
+}
+
+void QFxBlendedImage::setSecondaryUrl(const QString &url)
+{
+ if (secSrc == url)
+ return;
+ if (!secSrc.isEmpty())
+ QFxPixmap::cancelGet(secUrl,this);
+ secSrc = url;
+ secUrl = qmlContext(this)->resolvedUrl(url);
+ if (!secSrc.isEmpty())
+ QFxPixmap::get(qmlEngine(this), secUrl,this,SLOT(secondaryLoaded()));
+}
+
+/*!
+ \qmlproperty real BlendedImage::blend
+ The ratio used to blend the two images.
+
+ If blend has a value of 0, only the first image will be displayed.
+ If blend has a value of 1, only the second image will be displayed.
+*/
+qreal QFxBlendedImage::blend() const
+{
+ return _blend;
+}
+
+void QFxBlendedImage::setBlend(qreal b)
+{
+ _blend = b;
+ update();
+}
+
+/*!
+ \qmlproperty bool BlendedImage::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the BlendedImage is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+ */
+bool QFxBlendedImage::smoothTransform() const
+{
+ return _smooth;
+}
+
+void QFxBlendedImage::setSmoothTransform(bool s)
+{
+ if (_smooth == s)
+ return;
+ _smooth = s;
+ update();
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+
+void QFxBlendedImage::paintContents(QPainter &p)
+{
+ if (primSrc.isNull() && secSrc.isNull())
+ return;
+
+ if (_smooth) {
+ p.save();
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, _smooth);
+ }
+
+ if (_blend < 0.75)
+ p.drawPixmap(0, 0, primPix);
+ else
+ p.drawPixmap(0, 0, secPix);
+
+ if (_smooth) {
+ p.restore();
+ }
+}
+
+#elif defined(QFX_RENDER_OPENGL2)
+
+void QFxBlendedImage::paintGLContents(GLPainter &p)
+{
+ static DualTextureBlendShader *shader = 0;
+ if (!shader)
+ shader = new DualTextureBlendShader();
+
+ if (dirty) {
+ prim.clear();
+ sec.clear();
+ prim.setImage(primPix.toImage());
+ sec.setImage(secPix.toImage());
+
+ dirty = false;
+ }
+
+ if (prim.isNull() || sec.isNull()) {
+
+ return;
+ }
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+
+ float widthV = width();
+ float heightV = height();
+ if (!widthV)
+ widthV = qMax(primPix.width(), secPix.width());
+ if (!heightV)
+ heightV = qMax(primPix.height(), secPix.height());
+
+ vertices[0] = 0; vertices[1] = heightV;
+ vertices[2] = widthV; vertices[3] = heightV;
+ vertices[4] = 0; vertices[5] = 0;
+ vertices[6] = widthV; vertices[7] = 0;
+
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = 1; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = 1;
+ texVertices[6] = 1; texVertices[7] = 1;
+
+ if (_blend == 0 || _blend == 1) {
+ QGLShaderProgram *tshader = p.useTextureShader();
+
+ GLTexture *tex = 0;
+
+ if (_blend == 0)
+ tex = &prim;
+ else
+ tex = &sec;
+
+ tshader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ tshader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, tex->texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ tshader->disableAttributeArray(SingleTextureShader::Vertices);
+ tshader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ } else {
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, prim.texture());
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, sec.texture());
+
+ shader->enable();
+ shader->setOpacity(1);
+ qreal b = _blend;
+ if (b > 1) b = 1;
+ else if (b < 0) b = 0;
+ shader->setBlend(b);
+ shader->setTransform(p.activeTransform);
+
+ shader->setAttributeArray(DualTextureBlendShader::Vertices, vertices, 2);
+ shader->setAttributeArray(DualTextureBlendShader::TextureCoords, texVertices, 2);
+ shader->setAttributeArray(DualTextureBlendShader::BlendTextureCoords, texVertices, 2);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(DualTextureBlendShader::Vertices);
+ shader->disableAttributeArray(DualTextureBlendShader::TextureCoords);
+ shader->disableAttributeArray(DualTextureBlendShader::BlendTextureCoords);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE0);
+ }
+}
+#endif
+
+QML_DEFINE_TYPE(QFxBlendedImage,BlendedImage)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxblendedimage.h b/src/declarative/fx/qfxblendedimage.h
new file mode 100644
index 0000000..baf4b64
--- /dev/null
+++ b/src/declarative/fx/qfxblendedimage.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXBLENDEDIMAGE_H
+#define QFXBLENDEDIMAGE_H
+
+#include <QtDeclarative/qfxitem.h>
+#if defined(QFX_RENDER_OPENGL2)
+#include <gltexture.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QFxBlendedImage : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString primaryUrl READ primaryUrl WRITE setPrimaryUrl)
+ Q_PROPERTY(QString secondaryUrl READ secondaryUrl WRITE setSecondaryUrl)
+ Q_PROPERTY(qreal blend READ blend WRITE setBlend)
+ Q_PROPERTY(bool smooth READ smoothTransform WRITE setSmoothTransform)
+public:
+ QFxBlendedImage(QFxItem *parent=0);
+
+ QString primaryUrl() const;
+ void setPrimaryUrl(const QString &);
+
+ QString secondaryUrl() const;
+ void setSecondaryUrl(const QString &);
+
+ qreal blend() const;
+ void setBlend(qreal);
+
+ bool smoothTransform() const;
+ void setSmoothTransform(bool);
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#elif defined(QFX_RENDER_OPENGL2)
+ void paintGLContents(GLPainter &);
+#endif
+
+private Q_SLOTS:
+ void primaryLoaded();
+ void secondaryLoaded();
+
+private:
+ QString primSrc;
+ QString secSrc;
+ QUrl primUrl;
+ QUrl secUrl;
+
+ qreal _blend;
+ bool _smooth;
+ bool dirty;
+#if defined(QFX_RENDER_OPENGL2)
+ GLTexture prim;
+ GLTexture sec;
+#endif
+ QPixmap primPix;
+ QPixmap secPix;
+};
+QML_DECLARE_TYPE(QFxBlendedImage)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXBLENDEDIMAGE_H
diff --git a/src/declarative/fx/qfxblurfilter.cpp b/src/declarative/fx/qfxblurfilter.cpp
new file mode 100644
index 0000000..84799ec
--- /dev/null
+++ b/src/declarative/fx/qfxblurfilter.cpp
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxblurfilter.h"
+#include <private/qsimplecanvasitem_p.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glbasicshaders.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+class QFxBlurFilterPrivate
+{
+public:
+ QFxBlurFilterPrivate()
+ : radius(0)
+ {
+ }
+ qreal radius;
+};
+
+/*!
+ \qmlclass Blur
+ \brief The Blur filter blurs an item and its contents.
+ \inherits Filter
+
+ Blurring reduces the clarity of a visual item. The following example
+ shows an icon at a blur radius of 0, 5 and 10.
+
+ \table
+ \row
+ \o
+ \qml
+HorizontalLayout {
+ Image {
+ source: "icon.png"
+ filter: Blur { radius: 0 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Blur { radius: 5 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Blur { radius: 10 }
+ }
+}
+ \endqml
+ \row
+ \o \image blur_example.png
+ \endtable
+
+ Bluring is only supported when Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Blur filter has no effect.
+ */
+/*!
+ \internal
+ \class QFxBlurFilter
+ \ingroup group_effects
+ \brief The QFxBlurFilter class allows you to blur an item.
+*/
+
+QFxBlurFilter::QFxBlurFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxBlurFilterPrivate)
+{
+}
+
+QFxBlurFilter::~QFxBlurFilter()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \qmlproperty real Blur::radius
+
+ Sets the blur kernel radius.
+ The larger the radius the more blurry the item will appear.
+ A radius of 0 (or less) is equivalent to no blur.
+ */
+
+/*!
+ \property QFxBlurFilter::radius
+ \brief the radius of the blur.
+*/
+qreal QFxBlurFilter::radius() const
+{
+ return d->radius;
+}
+
+void QFxBlurFilter::setRadius(qreal radius)
+{
+ if (d->radius == radius) return;
+ d->radius = radius;
+ emit radiusChanged(radius);
+ update();
+}
+
+QRectF QFxBlurFilter::itemBoundingRect(const QRectF &r) const
+{
+ QRectF rv = r;
+ if (d->radius > 0)
+ rv.adjust(-d->radius, -d->radius, d->radius, d->radius);
+ return rv;
+}
+
+#include <math.h>
+void QFxBlurFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+#if 1
+ if (d->radius <= 0) {
+ renderToScreen();
+ return;
+ }
+ float radius = d->radius;
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+ float blurScale = 1.0;
+ QRect tr = QRect(QPoint(0, 0), r.size() * blurScale);
+ radius *= blurScale;
+
+ QGLFramebufferObject *fbo = renderToFBO(blurScale);
+ if (!fbo)
+ return;
+
+ float height = r.height();
+ float width = r.width();
+
+ float texWidth = float(tr.width()) / float(fbo->width());
+ float texHeight = float(tr.height()) / float(fbo->height());
+
+ int steps = int(::ceil(radius));
+ int dispSteps = int(::ceil(d->radius));
+ float xstep = texWidth * radius / float(steps * fbo->width());
+ float xinc = steps / float(fbo->width());
+
+ glDisable(GL_BLEND);
+
+ // Render x pass
+ QSize xSize(tr.width() + 2 * steps, tr.height());
+ QGLFramebufferObject *xBlur = acquireFBO(xSize);
+ float xWidth = float(xSize.width()) / float(xBlur->width());
+ float xHeight = float(xSize.height()) / float(xBlur->height());
+ {
+ xBlur->bind();
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ glClearColor(0,0,0,0);
+ glDisable(GL_SCISSOR_TEST);
+ glViewport(0, 0, xBlur->width(), xBlur->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float vert[] = { 0, xHeight,
+ xWidth, xHeight,
+ 0, 0,
+ xWidth, 0 };
+ float texVert[] = { -xinc, 0,
+ texWidth + xinc, 0,
+ -xinc, texHeight,
+ texWidth + xinc, texHeight };
+
+ QMatrix4x4 trans;
+ trans.translate(-1, -1);
+ trans.scale(2, 2);
+ BlurTextureShader *shader = item->basicShaders()->blurTexture();
+ shader->enable();
+ shader->setTransform(trans);
+ if (steps > 1) {
+ shader->setStep(xstep * 2);
+ shader->setSteps(steps / 2);
+ } else {
+ shader->setStep(xstep);
+ shader->setSteps(steps);
+ }
+ shader->setMode(BlurTextureShader::Horizontal);
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(BlurTextureShader::Vertices);
+ shader->disableAttributeArray(BlurTextureShader::TextureCoords);
+ xBlur->release();
+ }
+
+ // Render y pass
+ QSize ySize(xSize.width(), tr.height() + 2 * steps);
+ QGLFramebufferObject *yBlur = acquireFBO(ySize);
+
+ float yWidth = float(ySize.width()) / float(yBlur->width());
+ float yHeight = float(ySize.height()) / float(yBlur->height());
+ float ystep = radius / float(steps * xBlur->height());
+ float yinc = steps / float(xBlur->height());
+ {
+ yBlur->bind();
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ glClearColor(0,0,0,0);
+ glDisable(GL_SCISSOR_TEST);
+ glViewport(0, 0, yBlur->width(), yBlur->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float vert[] = { 0, yHeight,
+ yWidth, yHeight,
+ 0, 0,
+ yWidth, 0 };
+ float texVert[] = { 0, -yinc,
+ xWidth, -yinc,
+ 0, xHeight + yinc,
+ xWidth, xHeight + yinc };
+
+ QMatrix4x4 trans;
+ trans.translate(-1, -1);
+ trans.scale(2, 2);
+ BlurTextureShader *shader = item->basicShaders()->blurTexture();
+ shader->enable();
+ shader->setTransform(trans);
+ if (steps > 1) {
+ shader->setStep(ystep * 2);
+ shader->setSteps(steps / 2);
+ } else {
+ shader->setStep(ystep);
+ shader->setSteps(steps);
+ }
+ shader->setMode(BlurTextureShader::Vertical);
+
+ glBindTexture(GL_TEXTURE_2D, xBlur->texture());
+
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(BlurTextureShader::Vertices);
+ shader->disableAttributeArray(BlurTextureShader::TextureCoords);
+ yBlur->release();
+ }
+
+ glEnable(GL_BLEND);
+
+ // Render display pass
+ {
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ float vert[] = { -dispSteps, height + dispSteps,
+ width + dispSteps, height + dispSteps,
+ -dispSteps, -dispSteps,
+ width + dispSteps, -dispSteps };
+ float texVert[] = { 0, 0,
+ yWidth, 0,
+ 0, yHeight,
+ yWidth, yHeight };
+ SingleTextureShader *shader = item->basicShaders()->singleTexture();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+
+ glBindTexture(GL_TEXTURE_2D, yBlur->texture());
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVert, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ releaseFBO(yBlur);
+ releaseFBO(xBlur);
+ releaseFBO(fbo);
+#else
+#if 0
+ if (d->radius <= 0) {
+ renderToScreen();
+ return;
+ }
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+
+ float scale = 0.5;
+ float scalePercent = scale / d->radius;
+ QGLFramebufferObject *fbo = renderToFBO(scalePercent);
+ if (!fbo)
+ return;
+
+ QGLFramebufferObject *xfbo = acquireFBO(QSize(scale * r.width(), fbo->height()));
+ QGLFramebufferObject *yfbo = acquireFBO(QSize(scale * r.width(), scale * r.height()));
+
+
+ BlurTextureShader *shader = item->basicShaders()->blurTexture();
+ shader->enable();
+ shader->setTransform(QMatrix4x4());
+
+ // Render up - x
+ {
+ shader->setMode(BlurTextureShader::Horizontal);
+ shader->setStep(1. / float(xfbo->width()));
+
+ GLSaveViewport vp;
+ xfbo->bind();
+ glClearColor(0,0,0,0);
+ glViewport(0, 0, xfbo->width(), xfbo->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float oWidth = -1. + 2. * float(r.width()) * scale / float(xfbo->width());
+ float oHeight = -1. + 2. * float(r.height()) * scalePercent / float(xfbo->height());
+ float vert[] = {
+ -1, -1,
+ oWidth, -1,
+ -1, oHeight,
+
+ -1, oHeight,
+ oWidth, oHeight,
+ oWidth, -1
+ };
+
+ float tWidth = r.width() * scalePercent / fbo->width();
+ float tHeight = r.height() * scalePercent / fbo->height();
+ float texVert[] = {
+ 0, 0,
+ tWidth, 0,
+ 0, tHeight,
+
+ 0, tHeight,
+ tWidth, tHeight,
+ tWidth, 0
+ };
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ xfbo->release();
+ }
+
+ // Render up - y
+ {
+ shader->setMode(BlurTextureShader::Vertical);
+ shader->setStep(1. / float(yfbo->height()));
+
+ GLSaveViewport vp;
+ yfbo->bind();
+ glClearColor(0,0,0,0);
+ glViewport(0, 0, yfbo->width(), yfbo->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float oWidth = -1. + 2. * r.width() * scale / yfbo->width();
+ float oHeight = -1. + 2. * r.height() * scale / yfbo->height();
+ float vert[] = {
+ -1, -1,
+ oWidth, -1,
+ -1, oHeight,
+
+ -1, oHeight,
+ oWidth, oHeight,
+ oWidth, -1
+ };
+
+ float tWidth = r.width() * scale / xfbo->width();
+ float tHeight = r.height() * scalePercent / xfbo->height();
+ float texVert[] = {
+ 0, 0,
+ tWidth, 0,
+ 0, tHeight,
+
+ 0, tHeight,
+ tWidth, tHeight,
+ tWidth, 0
+ };
+
+ glBindTexture(GL_TEXTURE_2D, xfbo->texture());
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ yfbo->release();
+ }
+
+ shader->disableAttributeArray(BlurTextureShader::Vertices);
+ shader->disableAttributeArray(BlurTextureShader::TextureCoords);
+
+ float width = r.width();
+ float height = r.height();
+ //paint to screen
+ {
+ float texWidth = r.width() * scale / float(yfbo->width());
+ float texHeight = r.height() * scale / float(yfbo->height());
+
+ GLfloat vertices[] = { 0, height,
+ width, height,
+ 0, 0,
+ width, 0 };
+ GLfloat texVertices[] = { 0, 0,
+ texWidth, 0,
+ 0, texHeight,
+ texWidth, texHeight };
+
+ glBindTexture(GL_TEXTURE_2D, yfbo->texture());
+
+ SingleTextureOpacityShader *shader =
+ item->basicShaders()->singleTextureOpacity();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+ shader->setOpacity(p.activeOpacity);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::TextureCoords, texVertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::Vertices);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::TextureCoords);
+ }
+
+
+ releaseFBO(fbo);
+ releaseFBO(xfbo);
+ releaseFBO(yfbo);
+#endif
+#endif
+#else
+ Q_UNUSED(p);
+#endif
+
+}
+
+QML_DEFINE_TYPE(QFxBlurFilter,Blur)
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxblurfilter.h b/src/declarative/fx/qfxblurfilter.h
new file mode 100644
index 0000000..90285de
--- /dev/null
+++ b/src/declarative/fx/qfxblurfilter.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXBLURFILTER_H
+#define QFXBLURFILTER_H
+
+#include <QtDeclarative/qsimplecanvasfilter.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxBlurFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxBlurFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+public:
+ QFxBlurFilter(QObject *parent=0);
+ virtual ~QFxBlurFilter();
+
+ qreal radius() const;
+ void setRadius(qreal);
+
+Q_SIGNALS:
+ void radiusChanged(qreal);
+
+protected:
+ virtual QRectF itemBoundingRect(const QRectF &) const;
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+
+private:
+ QFxBlurFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxBlurFilter)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXBLURFILTER_H
diff --git a/src/declarative/fx/qfxcomponentinstance.cpp b/src/declarative/fx/qfxcomponentinstance.cpp
new file mode 100644
index 0000000..d3f7061
--- /dev/null
+++ b/src/declarative/fx/qfxcomponentinstance.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxcomponentinstance.h"
+#include "qfxcomponentinstance_p.h"
+#include <qfxperf.h>
+#include <qfxcontentwrapper.h>
+#include <QtDeclarative/qmlinfo.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxComponentInstance,ComponentInstance)
+
+/*!
+ \internal
+ \class QFxComponentInstance ComponentInstance
+
+ \brief The QFxComponentInstance class provides a way to instantiate an item from a component.
+ */
+
+/*!
+ \qmlclass ComponentInstance QFxComponentInstance
+ \brief The ComponentInstance item allows you to instantiate a \l{Component}.
+
+ \qml
+ Item {
+ Component {
+ id: RedSquare
+ Rect { color: "red"; width: 10; height: 10 }
+ }
+
+ ComponentInstance { component: RedSquare }
+ }
+ \endqml
+*/
+QFxComponentInstance::QFxComponentInstance(QFxItem *parent)
+ : QFxItem(*(new QFxComponentInstancePrivate), parent)
+{
+ setOptions(IsFocusRealm);
+}
+
+QFxComponentInstance::QFxComponentInstance(QFxComponentInstancePrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ setOptions(IsFocusRealm);
+}
+
+/*!
+ \qmlproperty Component QFxComponentInstance::component
+
+ This property holds the component to instantiate.
+*/
+QmlComponent *QFxComponentInstance::component() const
+{
+ Q_D(const QFxComponentInstance);
+ return d->component;
+}
+
+void QFxComponentInstance::setComponent(QmlComponent *c)
+{
+ Q_D(QFxComponentInstance);
+ if (d->component) {
+ qmlInfo(this) << "component is a write-once property.";
+ return;
+ }
+ d->component = c;
+ create();
+}
+
+void QFxComponentInstance::create()
+{
+ Q_D(QFxComponentInstance);
+ if (d->component) {
+ QObject *obj= d->component->create(qmlContext(this));
+ if (obj) {
+ QFxItem *objitem = qobject_cast<QFxItem *>(obj);
+ if (objitem) {
+ d->instance = objitem;
+ objitem->setItemParent(this);
+ objitem->setFocus(true);
+ connect(objitem, SIGNAL(widthChanged()), this, SLOT(updateSize()));
+ connect(objitem, SIGNAL(heightChanged()), this, SLOT(updateSize()));
+ updateSize();
+ emit instanceChanged();
+ } else {
+ delete obj;
+ }
+ }
+ }
+}
+
+void QFxComponentInstance::updateSize()
+{
+ QFxItem *i = instance();
+ if (i) {
+ if (!widthValid())
+ setImplicitWidth(i->width());
+ if (!heightValid())
+ setImplicitHeight(i->height());
+ }
+}
+
+/*!
+ \qmlproperty Item QFxComponentInstance::instance
+
+ This property holds the instantiated component.
+*/
+QFxItem *QFxComponentInstance::instance() const
+{
+ Q_D(const QFxComponentInstance);
+ return d->instance;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxcomponentinstance.h b/src/declarative/fx/qfxcomponentinstance.h
new file mode 100644
index 0000000..e749272
--- /dev/null
+++ b/src/declarative/fx/qfxcomponentinstance.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCOMPONENTINSTANCE_H
+#define QFXCOMPONENTINSTANCE_H
+
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxComponentInstancePrivate;
+class Q_DECLARATIVE_EXPORT QFxComponentInstance : public QFxItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QmlComponent *component READ component WRITE setComponent)
+ Q_PROPERTY(QFxItem *instance READ instance)
+ Q_CLASSINFO("DefaultProperty", "component")
+public:
+ QFxComponentInstance(QFxItem *parent=0);
+
+ QmlComponent *component() const;
+ void setComponent(QmlComponent *);
+
+ QFxItem *instance() const;
+
+Q_SIGNALS:
+ void instanceChanged();
+
+private slots:
+ void updateSize();
+
+private:
+ void create();
+
+protected:
+ QFxComponentInstance(QFxComponentInstancePrivate &dd, QFxItem *parent);
+
+private:
+ Q_DECLARE_PRIVATE(QFxComponentInstance)
+};
+QML_DECLARE_TYPE(QFxComponentInstance)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXCOMPONENTINSTANCE_H
diff --git a/src/declarative/fx/qfxcomponentinstance_p.h b/src/declarative/fx/qfxcomponentinstance_p.h
new file mode 100644
index 0000000..defeb74
--- /dev/null
+++ b/src/declarative/fx/qfxcomponentinstance_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCOMPONENTINSTANCE_P_H
+#define QFXCOMPONENTINSTANCE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxitem_p.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxComponentInstancePrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxComponentInstance)
+
+public:
+ QFxComponentInstancePrivate()
+ : component(0), instance(0)
+ {
+ }
+
+ QmlComponent *component;
+ QFxItem *instance;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXCOMPONENTINSTANCE_P_H
diff --git a/src/declarative/fx/qfxcontentwrapper.cpp b/src/declarative/fx/qfxcontentwrapper.cpp
new file mode 100644
index 0000000..482442b
--- /dev/null
+++ b/src/declarative/fx/qfxcontentwrapper.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxcontentwrapper.h"
+#include "qfxcontentwrapper_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxContentWrapper,ContentWrapper)
+
+/*!
+ \qmlclass ContentWrapper QFxContentWrapper
+ \ingroup group_utility
+ \brief ContentWrapper provides a component which contains content.
+ \inherits Item
+
+ In some cases the content of a component is not defined by the component itself.
+ For example, the items placed in a group box need to be specified external to
+ group box component definition itself.
+ In cases like these \l Content can be used to specify at what location in the component
+ the content should be placed. It is used in conjuntion with the \e content property of
+ ContentWrapper: any items listed as content will be placed in the location
+ specified by Content. The component containing the Content must be of type
+ ContentWrapper.
+
+ GroupBox component definition:
+ \quotefile doc/src/snippets/declarative/GroupBox.qml
+
+ \bold Note that in the above component definition ContentWrapper's \e children
+ property is specified explicitly since \e content is the default property.
+
+ Component use:
+ \table
+ \row \o \image content.png
+ \o \quotefile doc/src/snippets/declarative/content.qml
+ \endtable
+
+ \sa Content
+*/
+
+QFxContentWrapper::QFxContentWrapper(QFxItem *parent)
+: QFxItem(*(new QFxContentWrapperPrivate), parent)
+{
+}
+
+QFxContentWrapper::QFxContentWrapper(QFxContentWrapperPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+}
+
+/*!
+ \qmlproperty list<Item> ContentWrapper::content
+
+ Contains the list of elements to replace the \l Content
+ placeholder.
+
+ \sa Content
+*/
+QList<QFxItem *> *QFxContentWrapper::content()
+{
+ Q_D(QFxContentWrapper);
+ return &(d->_content);
+}
+
+void QFxContentWrapper::componentComplete()
+{
+ QFxItem::componentComplete();
+ if (content()->size() < 1)
+ return;
+
+ QList<QSimpleCanvasItem *> nodes;
+ nodes.append(this);
+ QFxItem *target = findContent(nodes);
+ if (!target)
+ return;
+ target = target->itemParent();
+
+ QList<QFxItem*> myContent(*content());
+ for (int ii = 0; ii < myContent.count(); ++ii)
+ myContent.at(ii)->setParent(target);
+}
+
+QFxItem *QFxContentWrapper::findContent(QList<QSimpleCanvasItem *> &nodes)
+{
+ QSimpleCanvasItem *item = nodes.takeFirst();
+ if (qobject_cast<QFxContent*>(item))
+ return static_cast<QFxItem *>(item);
+ nodes << item->children();
+ if (nodes.isEmpty())
+ return 0;
+ return findContent(nodes);
+}
+
+QML_DEFINE_TYPE(QFxContent,Content)
+
+/*!
+ \qmlclass Content QFxContent
+ \ingroup group_utility
+ \brief Content is used as a placeholder for the content of a component.
+ \inherits Item
+
+ The Content element is used to place content within a component.
+ See \l ContentWrapper for usage.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxcontentwrapper.h b/src/declarative/fx/qfxcontentwrapper.h
new file mode 100644
index 0000000..d8fe0b8
--- /dev/null
+++ b/src/declarative/fx/qfxcontentwrapper.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCONTENTWRAPPER_H
+#define QFXCONTENTWRAPPER_H
+
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxContentWrapperPrivate;
+class Q_DECLARATIVE_EXPORT QFxContentWrapper : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QList<QFxItem *>* content READ content DESIGNABLE false)
+ Q_CLASSINFO("DefaultProperty", "content")
+public:
+ QFxContentWrapper(QFxItem *parent=0);
+
+ QList<QFxItem *> *content();
+
+private:
+ void create();
+ QFxItem *findContent(QList<QSimpleCanvasItem *> &nodes);
+
+protected:
+ void componentComplete();
+ QFxContentWrapper(QFxContentWrapperPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DECLARE_PRIVATE(QFxContentWrapper)
+};
+QML_DECLARE_TYPE(QFxContentWrapper)
+
+class Q_DECLARATIVE_EXPORT QFxContent : public QFxItem
+{
+ Q_OBJECT
+public:
+ QFxContent(QFxItem *parent=0) : QFxItem(parent) {}
+};
+QML_DECLARE_TYPE(QFxContent)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXCONTENTWRAPPER_H
diff --git a/src/declarative/fx/qfxcontentwrapper_p.h b/src/declarative/fx/qfxcontentwrapper_p.h
new file mode 100644
index 0000000..a75fa1e
--- /dev/null
+++ b/src/declarative/fx/qfxcontentwrapper_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCONTENTWRAPPER_P_H
+#define QFXCONTENTWRAPPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxitem_p.h"
+#include "qfxcontentwrapper.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxContentWrapperPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxContentWrapper)
+public:
+ QFxContentWrapperPrivate() { }
+
+ QList<QFxItem *> _content;
+};
+
+QT_END_NAMESPACE
+#endif // QFXCONTENTWRAPPER_P_H
diff --git a/src/declarative/fx/qfxevents.cpp b/src/declarative/fx/qfxevents.cpp
new file mode 100644
index 0000000..94c2d2e
--- /dev/null
+++ b/src/declarative/fx/qfxevents.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxevents_p.h"
+
+QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass KeyEvent QFxKeyEvent
+ \brief The KeyEvent object provides information about a key event.
+
+ For example, the following changes the Item's state property when the Enter
+ key is pressed:
+ \qml
+Item {
+ focus: true
+ onKeyPress: { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; }
+}
+ \endqml
+
+ The \l KeyActions object could also be used to achieve the above with
+ a clearer syntax.
+
+ \sa KeyActions
+*/
+
+/*!
+ \internal
+ \class QFxKeyEvent
+*/
+
+/*!
+ \qmlproperty int KeyEvent::key
+
+ This property holds the code of the key that was pressed or released.
+
+ See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are
+ independent of the underlying window system. Note that this
+ function does not distinguish between capital and non-capital
+ letters, use the text() function (returning the Unicode text the
+ key generated) for this purpose.
+
+ A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not
+ the result of a known key; for example, it may be the result of
+ a compose sequence, a keyboard macro, or due to key event
+ compression.
+*/
+
+/*!
+ \qmlproperty string KeyEvent::text
+
+ This property holds the Unicode text that the key generated.
+ The text returned can be an empty string in cases where modifier keys,
+ such as Shift, Control, Alt, and Meta, are being pressed or released.
+ In such cases \c key will contain a valid value
+*/
+
+/*!
+ \qmlproperty bool KeyEvent::isAutoRepeat
+
+ This property holds whether this event comes from an auto-repeating key.
+*/
+
+/*!
+ \qmlproperty int KeyEvent::count
+
+ This property holds the number of keys involved in this event. If \l KeyEvent::text
+ is not empty, this is simply the length of the string.
+*/
+
+/*!
+ \qmlclass MouseEvent QFxMouseEvent
+ \brief The MouseEvent object provides information about a mouse event.
+
+ The position of the mouse can be found via the x and y properties.
+ The button that caused the event is available via the button property.
+*/
+
+/*!
+ \internal
+ \class QFxMouseEvent
+*/
+
+/*!
+ \qmlproperty int MouseEvent::x
+ \qmlproperty int MouseEvent::y
+
+ These properties hold the position of the mouse event.
+*/
+
+/*!
+ \qmlproperty enum MouseEvent::button
+
+ This property holds the button that caused the event. It can be one of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MidButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty int MouseEvent::buttons
+
+ This property holds the mouse buttons pressed when the event was generated.
+ For mouse move events, this is all buttons that are pressed down. For mouse
+ press and double click events this includes the button that caused the event.
+ For mouse release events this excludes the button that caused the event.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MidButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty int MouseEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Left mouse button click:
+ \qml
+MouseRegion {
+ onClick: { if (mouse.button == Qt.LeftButton && mouse.modifiers & Qt.ShiftModifier) doSomething(); }
+}
+ \endqml
+*/
+
+QML_DEFINE_NOCREATE_TYPE(QFxKeyEvent)
+QML_DEFINE_NOCREATE_TYPE(QFxMouseEvent)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxevents_p.h b/src/declarative/fx/qfxevents_p.h
new file mode 100644
index 0000000..2eb29af
--- /dev/null
+++ b/src/declarative/fx/qfxevents_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXEVENTS_P_H
+#define QFXEVENTS_P_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFxKeyEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key)
+ Q_PROPERTY(QString text READ text)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QFxKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
+ : event(type, key, modifiers, text, autorep, count) { event.setAccepted(false); }
+ QFxKeyEvent(const QKeyEvent &ke)
+ : event(ke) { event.setAccepted(false); }
+
+ int key() const { return event.key(); }
+ QString text() const { return event.text(); }
+ int modifiers() const { return event.modifiers(); }
+ bool isAutoRepeat() const { return event.isAutoRepeat(); }
+ int count() const { return event.count(); }
+
+ bool isAccepted() { return event.isAccepted(); }
+ void setAccepted(bool accepted) { event.setAccepted(accepted); }
+
+private:
+ QKeyEvent event;
+};
+
+QML_DECLARE_TYPE(QFxKeyEvent)
+
+class QFxMouseEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x)
+ Q_PROPERTY(int y READ y)
+ Q_PROPERTY(int button READ button)
+ Q_PROPERTY(int buttons READ buttons)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool wasHeld READ wasHeld)
+ Q_PROPERTY(bool isClick READ isClick)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QFxMouseEvent(int x, int y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers
+ , bool isClick=false, bool wasHeld=false)
+ : _x(x), _y(y), _button(button), _buttons(buttons), _modifiers(modifiers)
+ , _wasHeld(wasHeld), _isClick(isClick), _accepted(false) {}
+
+ int x() const { return _x; }
+ int y() const { return _y; }
+ int button() const { return _button; }
+ int buttons() const { return _buttons; }
+ int modifiers() const { return _modifiers; }
+ bool wasHeld() const { return _wasHeld; }
+ bool isClick() const { return _isClick; }
+
+ bool isAccepted() { return _accepted; }
+ void setAccepted(bool accepted) { _accepted = accepted; }
+
+private:
+ int _x;
+ int _y;
+ Qt::MouseButton _button;
+ Qt::MouseButtons _buttons;
+ Qt::KeyboardModifiers _modifiers;
+ bool _wasHeld;
+ bool _isClick;
+ bool _accepted;
+};
+
+QML_DECLARE_TYPE(QFxMouseEvent)
+
+QT_END_NAMESPACE
+
+#endif // QFXEVENTS_P_H
diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp
new file mode 100644
index 0000000..bc4a5fc
--- /dev/null
+++ b/src/declarative/fx/qfxflickable.cpp
@@ -0,0 +1,1153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxflickable.h"
+#include "qfxflickable_p.h"
+
+#include <QGraphicsSceneMouseEvent>
+#include <QPointer>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+ElasticValue::ElasticValue(QmlTimeLineValue &val)
+ : _value(val)
+{
+ _to = _value.value();
+ _myValue = _to;
+ _velocity = 0;
+}
+
+void ElasticValue::setValue(qreal to)
+{
+ if (_to != to) {
+ _to = to;
+ _startTime.start();
+ if (state() != Running)
+ start();
+ }
+}
+
+void ElasticValue::clear()
+{
+ stop();
+ _velocity = 0.0;
+ _myValue = _value.value();
+}
+
+void ElasticValue::updateCurrentTime(int)
+{
+ const qreal Tension = 0.1;
+ int elapsed = _startTime.restart();
+ if (!elapsed)
+ return;
+ qreal dist = _to - _value.value();
+ qreal move = Tension * dist * qAbs(dist);
+ if (elapsed < 100 && _velocity != 0.0)
+ move = (elapsed * move + (100 - elapsed) * _velocity) / 100;
+ _myValue += move * elapsed / 1000;
+ _value.setValue(qRound(_myValue)); // moving sub-pixel can be ugly.
+// _value.setValue(_myValue);
+ _velocity = move;
+ if (qAbs(_velocity) < 5.0)
+ clear();
+ emit updated();
+}
+
+QFxFlickablePrivate::QFxFlickablePrivate()
+ : _flick(new QFxItem), _moveX(_flick, &QFxItem::setX), _moveY(_flick, &QFxItem::setY)
+ , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false)
+ , pressed(false), maxVelocity(-1), locked(false), dragMode(QFxFlickable::Hard)
+ , elasticY(_moveY), elasticX(_moveX), velocityDecay(100), xVelocity(this), yVelocity(this)
+ , vTime(0), atXEnd(false), atXBeginning(true), pageXPosition(0.), pageWidth(0.)
+ , atYEnd(false), atYBeginning(true), pageYPosition(0.), pageHeight(0.)
+{
+ fixupXEvent = QmlTimeLineEvent::timeLineEvent<QFxFlickablePrivate, &QFxFlickablePrivate::fixupX>(&_moveX, this);
+ fixupYEvent = QmlTimeLineEvent::timeLineEvent<QFxFlickablePrivate, &QFxFlickablePrivate::fixupY>(&_moveY, this);
+}
+
+void QFxFlickablePrivate::init()
+{
+ Q_Q(QFxFlickable);
+ _flick->setParent(q);
+ QObject::connect(&_tl, SIGNAL(updated()), q, SLOT(ticked()));
+ QObject::connect(&_tl, SIGNAL(completed()), q, SLOT(movementEnding()));
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setOptions(QSimpleCanvasItem::ChildMouseFilter | QSimpleCanvasItem::MouseEvents);
+ QObject::connect(_flick, SIGNAL(leftChanged()), q, SIGNAL(positionChanged()));
+ QObject::connect(_flick, SIGNAL(topChanged()), q, SIGNAL(positionChanged()));
+ QObject::connect(&elasticX, SIGNAL(updated()), q, SLOT(ticked()));
+ QObject::connect(&elasticY, SIGNAL(updated()), q, SLOT(ticked()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(heightChange()));
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(widthChange()));
+}
+
+void QFxFlickablePrivate::fixupX()
+{
+ Q_Q(QFxFlickable);
+ if (!q->xflick() || _moveX.timeLine())
+ return;
+
+ vTime = _tl.time();
+
+ if (_moveX.value() > q->minXExtent() || q->maxXExtent() > 0) {
+ _tl.clear();
+ _tl.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ flicked = false;
+ //emit flickingChanged();
+ } else if (_moveX.value() < q->maxXExtent()) {
+ _tl.clear();
+ _tl.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ flicked = false;
+ //emit flickingChanged();
+ }
+}
+
+void QFxFlickablePrivate::fixupY()
+{
+ Q_Q(QFxFlickable);
+ if (!q->yflick() || _moveY.timeLine())
+ return;
+
+ vTime = _tl.time();
+
+ if (_moveY.value() > q->minYExtent() || (q->maxYExtent() > q->minYExtent())) {
+ _tl.clear();
+ _tl.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ //emit flickingChanged();
+ } else if (_moveY.value() < q->maxYExtent()) {
+ _tl.clear();
+ _tl.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ //emit flickingChanged();
+ } else {
+ flicked = false;
+ }
+}
+
+void QFxFlickablePrivate::updateBeginningEnd()
+{
+ Q_Q(QFxFlickable);
+ bool pageChange = false;
+ bool atBoundaryChange = false;
+
+ // Vertical
+ const int viewheight = q->height();
+ const int maxyextent = int(-q->maxYExtent());
+ const qreal ypos = -_moveY.value();
+ qreal pagePos = ((ypos * 100.0) / (maxyextent + viewheight)) / 100.0;
+ qreal pageSize = ((viewheight * 100.0) / (maxyextent + viewheight)) / 100.0;
+ bool atBeginning = (ypos <= 0.0);
+ bool atEnd = (maxyextent <= ypos);
+
+ if (pageSize != pageHeight) {
+ pageHeight = pageSize;
+ pageChange = true;
+ }
+ if (pagePos != pageYPosition) {
+ pageYPosition = pagePos;
+ pageChange = true;
+ }
+ if (atBeginning != atYBeginning) {
+ atYBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != atYEnd) {
+ atYEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ // Horizontal
+ const int viewwidth = q->width();
+ const int maxxextent = int(-q->maxXExtent());
+ const qreal xpos = -_moveX.value();
+ pagePos = ((xpos * 100.0) / (maxxextent + viewwidth)) / 100.0;
+ pageSize = ((viewwidth * 100.0) / (maxxextent + viewwidth)) / 100.0;
+ atBeginning = (xpos <= 0.0);
+ atEnd = (maxxextent <= xpos);
+
+ if (pageSize != pageWidth) {
+ pageWidth = pageSize;
+ pageChange = true;
+ }
+ if (pagePos != pageXPosition) {
+ pageXPosition = pagePos;
+ pageChange = true;
+ }
+ if (atBeginning != atXBeginning) {
+ atXBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != atXEnd) {
+ atXEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ if (pageChange)
+ emit q->pageChanged();
+ if (atBoundaryChange)
+ emit q->isAtBoundaryChanged();
+}
+
+static const int FlickThreshold = 5;
+
+QML_DEFINE_TYPE(QFxFlickable,Flickable)
+
+/*!
+ \qmlclass Flickable
+ \brief The Flickable item provides a surface that can be "flicked".
+ \inherits Item
+
+ Flickable places its children on a surface that can be dragged and flicked.
+
+ \code
+ Flickable {
+ width: 200; height: 200; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+ }
+ \endcode
+
+ \image flickable.gif
+
+ \note Flickable does not automatically clip its contents. If
+ it is not full-screen it is likely that \c clip should be set
+ to true.
+
+ \note Due to an implementation detail items placed inside a flickable cannot anchor to it by
+ id, use 'parent' instead.
+*/
+
+/*!
+ \internal
+ \class QFxFlickable
+ \brief The QFxFlickable class provides a view that can be "flicked".
+
+ \ingroup group_widgets
+
+ QFxFlickable allows its children to be dragged and flicked.
+
+\code
+Flickable {
+ width: 320; height: 480; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+}
+\endcode
+
+ Note that QFxFlickable does not automatically clip its contents. If
+ it is not full-screen it is likely that QFxItem::clip should be set
+ to true.
+
+*/
+
+QFxFlickable::QFxFlickable(QFxItem *parent)
+ : QFxItem(*(new QFxFlickablePrivate), parent)
+{
+ Q_D(QFxFlickable);
+ d->init();
+}
+
+QFxFlickable::QFxFlickable(QFxFlickablePrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxFlickable);
+ d->init();
+}
+
+QFxFlickable::~QFxFlickable()
+{
+}
+
+/*!
+ \qmlproperty int Flickable::xPosition
+ \qmlproperty int Flickable::yPosition
+
+ These properties hold the surface coordinate currently at the top-left
+ corner of the Flickable. For example, if you flick an image up 100 pixels,
+ \c yPosition will be 100.
+*/
+
+/*!
+ \property QFxFlickable::xPosition
+ \brief the x position of the view.
+
+ The xPosition represents the left-most visible coordinate in the view.
+*/
+qreal QFxFlickable::xPosition() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveX.value();
+}
+
+void QFxFlickable::setXPosition(qreal pos)
+{
+ Q_D(QFxFlickable);
+ pos = qRound(pos);
+ if (-pos != d->_moveX.value()) {
+ d->_tl.reset(d->_moveX);
+ d->_moveX.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+/*!
+ \property QFxFlickable::yPosition
+ \brief the y position of the view.
+
+ The yPosition represents the top-most visible coordinate in the view.
+*/
+qreal QFxFlickable::yPosition() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveY.value();
+}
+
+void QFxFlickable::setYPosition(qreal pos)
+{
+ Q_D(QFxFlickable);
+ pos = qRound(pos);
+ if (-pos != d->_moveY.value()) {
+ d->_tl.reset(d->_moveY);
+ d->_moveY.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+/*!
+ \qmlproperty bool Flickable::locked
+
+ A user cannot drag or flick a Flickable that is locked.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with Flickable's children: for example, you might want to
+ freeze a flickable map while viewing detailed information on a location popup that is a child of the Flickable.
+*/
+
+/*!
+ \property QFxFlickable::locked
+ \brief determines whether the user can move the view.
+
+ If the Flickable is locked, the user cannot move the view.
+*/
+bool QFxFlickable::isLocked() const
+{
+ Q_D(const QFxFlickable);
+ return d->locked;
+}
+
+void QFxFlickable::setLocked(bool lock)
+{
+ Q_D(QFxFlickable);
+ d->locked = lock;
+}
+
+/*!
+ \qmlproperty enumeration Flickable::dragMode
+ This property contains the kind of 'physics' applied when dragging the surface.
+
+ Two modes are supported:
+ \list
+ \i Hard - the view follows the user's input exactly.
+ \i Elastic - the view moves elastically in response to the user's input.
+ \endlist
+*/
+
+/*!
+ \property QFxFlickable::dragMode
+ \brief sets the kind of 'physics' applied when dragging the view.
+
+ Two modes are supported:
+ \list
+ \i Hard - the view follows the user's input exactly.
+ \i Elastic - the view moves elastically in response to the user's input.
+ \endlist
+*/
+QFxFlickable::DragMode QFxFlickable::dragMode() const
+{
+ Q_D(const QFxFlickable);
+ return d->dragMode;
+}
+
+void QFxFlickable::setDragMode(DragMode mode)
+{
+ Q_D(QFxFlickable);
+ d->dragMode = mode;
+}
+
+/*!
+ \qmlproperty real Flickable::xVelocity
+ \qmlproperty real Flickable::yVelocity
+
+ The instantaneous velocity of movement along the x and y axes, in pixels/sec.
+*/
+
+/*!
+ \property QFxFlickable::xVelocity
+ \brief provides the instantaneous velocity of movement in the x-axis (pixels/sec).
+*/
+qreal QFxFlickable::xVelocity() const
+{
+ Q_D(const QFxFlickable);
+ return d->xVelocity.value();
+}
+
+/*!
+ \property QFxFlickable::yVelocity
+ \brief provides the instantaneous velocity of movement in the y-axis (pixels/sec).
+*/
+qreal QFxFlickable::yVelocity() const
+{
+ Q_D(const QFxFlickable);
+ return d->yVelocity.value();
+}
+
+/*!
+ \qmlproperty bool Flickable::atXBeginning
+ \qmlproperty bool Flickable::atXEnd
+ \qmlproperty bool Flickable::atYBeginning
+ \qmlproperty bool Flickable::atYEnd
+
+ These properties are true if the flickable view is positioned at the beginning,
+ or end respecively.
+*/
+bool QFxFlickable::isAtXEnd() const
+{
+ Q_D(const QFxFlickable);
+ return d->atXEnd;
+}
+
+bool QFxFlickable::isAtXBeginning() const
+{
+ Q_D(const QFxFlickable);
+ return d->atXBeginning;
+}
+
+bool QFxFlickable::isAtYEnd() const
+{
+ Q_D(const QFxFlickable);
+ return d->atYEnd;
+}
+
+bool QFxFlickable::isAtYBeginning() const
+{
+ Q_D(const QFxFlickable);
+ return d->atYBeginning;
+}
+
+/*!
+ \qmlproperty real Flickable::pageXPosition
+ \qmlproperty real Flickable::pageWidth
+ \qmlproperty real Flickable::pageYPosition
+ \qmlproperty real Flickable::pageHeight
+
+ These properties describe the position and size of the currently viewed page.
+ The page size is defined as the percentage of the full view currently visible,
+ scaled to 0.0 - 1.0. The page position is also in the range 0.0 (beginning) to
+ 1.0 (end).
+
+ These properties are typically used to draw a scrollbar, for example:
+ \code
+ Rect {
+ opacity: 0.5; anchors.right: MyListView.right-2; width: 6
+ y: MyListView.pageYPosition * MyListView.height
+ height: MyListView.pageHeight * MyListView.height
+ }
+ \endcode
+*/
+qreal QFxFlickable::pageWidth() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageWidth;
+}
+
+qreal QFxFlickable::pageXPosition() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageXPosition;
+}
+
+qreal QFxFlickable::pageHeight() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageHeight;
+}
+
+qreal QFxFlickable::pageYPosition() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageYPosition;
+}
+
+void QFxFlickable::ticked()
+{
+ viewportMoved();
+}
+
+QFxItem *QFxFlickable::viewport()
+{
+ Q_D(QFxFlickable);
+ return d->_flick;
+}
+
+qreal QFxFlickable::visibleX() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveX.value();
+}
+
+qreal QFxFlickable::visibleY() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveY.value();
+}
+
+void QFxFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (!locked && _tl.isActive() && (qAbs(velocityX) > 10 || qAbs(velocityY) > 10))
+ stealMouse = true; // If we've been flicked then steal the click.
+ else
+ stealMouse = false;
+ pressed = true;
+ _tl.clear();
+ velocityX = -1;
+ velocityY = -1;
+ lastPos = QPoint();
+ lastPosTime.start();
+ pressPos = event->pos();
+ pressX = _moveX.value();
+ pressY = _moveY.value();
+ flicked = false;
+ pressTime.start();
+ if (dragMode == QFxFlickable::Elastic) {
+ elasticX.clear();
+ elasticY.clear();
+ }
+ velocityTime.start();
+}
+
+void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QFxFlickable);
+ if (locked || lastPosTime.isNull())
+ return;
+ bool rejectY = false;
+ bool rejectX = false;
+ bool moved = false;
+
+ if (q->yflick()) {
+ int dy = int(event->pos().y() - pressPos.y());
+ if (qAbs(dy) > FlickThreshold || pressTime.elapsed() > 200) {
+ qreal newY = dy + pressY;
+ const qreal minY = q->minYExtent();
+ const qreal maxY = q->maxYExtent();
+ if (newY > minY)
+ newY = minY + (newY - minY) / 2;
+ if (newY < maxY && maxY - minY < 0)
+ newY = maxY + (newY - maxY) / 2;
+ if (q->overShoot() || (newY <= minY && newY >= maxY)) {
+ if (dragMode == QFxFlickable::Hard)
+ _moveY.setValue(newY);
+ else
+ elasticY.setValue(newY);
+ moved = true;
+ } else if (!q->overShoot())
+ rejectY = true;
+ if (qAbs(dy) > FlickThreshold)
+ stealMouse = true;
+ }
+ }
+
+ if (q->xflick()) {
+ int dx = int(event->pos().x() - pressPos.x());
+ if (qAbs(dx) > FlickThreshold || pressTime.elapsed() > 200) {
+ qreal newX = dx + pressX;
+ if (q->overShoot() || (newX <= q->minXExtent() && newX >= q->maxXExtent())) {
+ if (dragMode == QFxFlickable::Hard)
+ _moveX.setValue(newX);
+ else
+ elasticX.setValue(newX);
+ moved = true;
+ } else if (!q->overShoot())
+ rejectX = true;
+ if (qAbs(dx) > FlickThreshold)
+ stealMouse = true;
+ }
+ }
+
+ if (!lastPos.isNull()) {
+ qreal elapsed = qreal(lastPosTime.restart()) / 1000.;
+ if (elapsed <= 0)
+ elapsed = 1;
+ if (q->yflick()) {
+ qreal diff = event->pos().y() - lastPos.y();
+ velocityY = diff / elapsed;
+ }
+
+ if (q->xflick()) {
+ qreal diff = event->pos().x() - lastPos.x();
+ velocityX = diff / elapsed;
+ }
+ }
+
+ if (rejectY) velocityY = 0;
+ if (rejectX) velocityX = 0;
+
+ if (moved) {
+ q->viewportMoved();
+ q->movementStarting();
+ }
+
+ lastPos = event->pos();
+}
+
+void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *)
+{
+ Q_Q(QFxFlickable);
+
+ pressed = false;
+ if (lastPosTime.isNull())
+ return;
+
+ if (dragMode == QFxFlickable::Elastic) {
+ elasticY.clear();
+ elasticX.clear();
+ }
+
+ vTime = _tl.time();
+ if (qAbs(velocityY) > 10) {
+ qreal maxDistance = -1;
+ // -ve velocity means list is moving up
+ if (velocityY > 0) {
+ if (_moveY.value() < q->minYExtent())
+ maxDistance = qAbs(q->minYExtent() -_moveY.value() + (overShoot?30:0));
+ } else {
+ if (_moveY.value() > q->maxYExtent())
+ maxDistance = qAbs(q->maxYExtent() - _moveY.value()) + (overShoot?30:0);
+ }
+ if (maxDistance > 0) {
+ qreal v = velocityY;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ _tl.accel(_moveY, v, 500, maxDistance);
+ _tl.execute(fixupYEvent);
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ } else {
+ fixupY();
+ }
+ } else {
+ fixupY();
+ }
+ if (qAbs(velocityX) > 10) {
+ qreal maxDistance = -1;
+ // -ve velocity means list is moving up
+ if (velocityX > 0) {
+ if (_moveX.value() < q->minXExtent())
+ maxDistance = qAbs(q->minXExtent()) -_moveX.value() + (overShoot?30:0);
+ } else {
+ if (_moveX.value() > q->maxXExtent())
+ maxDistance = qAbs(q->maxXExtent() - _moveX.value()) + (overShoot?30:0);
+ }
+ if (maxDistance > 0) {
+ qreal v = velocityX;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ _tl.accel(_moveX, v, 500, maxDistance);
+ _tl.execute(fixupXEvent);
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ } else {
+ fixupX();
+ }
+ } else {
+ fixupX();
+ }
+ stealMouse = false;
+ lastPosTime = QTime();
+
+ if (!_tl.isActive())
+ q->movementEnding();
+}
+
+void QFxFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ d->handleMousePressEvent(event);
+ event->accept();
+}
+
+void QFxFlickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ d->handleMouseMoveEvent(event);
+ event->accept();
+}
+
+void QFxFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ d->handleMouseReleaseEvent(event);
+ event->accept();
+}
+
+qreal QFxFlickable::minYExtent() const
+{
+ return 0.0;
+}
+
+qreal QFxFlickable::minXExtent() const
+{
+ return 0.0;
+}
+
+/* returns -ve */
+qreal QFxFlickable::maxXExtent() const
+{
+ return width() - vWidth();
+}
+/* returns -ve */
+qreal QFxFlickable::maxYExtent() const
+{
+ return height() - vHeight();
+}
+
+void QFxFlickable::viewportMoved()
+{
+ Q_D(QFxFlickable);
+ //XXX should look at moveX here as well
+ if (d->flicked && (d->_moveY.value() > minYExtent() + (d->overShoot?30:0)
+ || d->_moveY.value() < maxYExtent() - (d->overShoot?30:0))){
+ d->flicked = false;
+ emit flickingChanged();
+ emit flickEnded();
+ d->_tl.reset(d->_moveY);
+ d->fixupY();
+ }
+
+ int elapsed = d->velocityTime.elapsed();
+
+ if (elapsed) {
+ qreal prevY = d->lastFlickablePosition.x();
+ qreal prevX = d->lastFlickablePosition.y();
+ d->velocityTimeline.clear();
+ if (d->pressed) {
+ qreal xVelocity = (prevX - d->_moveX.value()) * 1000 / elapsed;
+ qreal yVelocity = (prevY - d->_moveY.value()) * 1000 / elapsed;
+ d->velocityTimeline.move(d->xVelocity, xVelocity, d->velocityDecay);
+ d->velocityTimeline.move(d->xVelocity, 0, d->velocityDecay);
+ d->velocityTimeline.move(d->yVelocity, yVelocity, d->velocityDecay);
+ d->velocityTimeline.move(d->yVelocity, 0, d->velocityDecay);
+ } else {
+ if (d->_tl.time() != d->vTime) {
+ qreal xVelocity = (prevX - d->_moveX.value()) * 1000 / (d->_tl.time() - d->vTime);
+ qreal yVelocity = (prevY - d->_moveY.value()) * 1000 / (d->_tl.time() - d->vTime);
+ d->xVelocity.setValue(xVelocity);
+ d->yVelocity.setValue(yVelocity);
+ }
+ d->vTime = d->_tl.time();
+ }
+ }
+
+ d->lastFlickablePosition = QPointF(d->_moveY.value(), d->_moveX.value());
+ d->velocityTime.restart();
+ d->updateBeginningEnd();
+}
+
+void QFxFlickablePrivate::data_removeAt(int)
+{
+ // ###
+}
+
+int QFxFlickablePrivate::data_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxFlickablePrivate::data_append(QObject *o)
+{
+ Q_Q(QFxFlickable);
+ QFxItem *i = qobject_cast<QFxItem *>(o);
+ if (i)
+ _flick->children()->append(i);
+ else
+ o->setParent(q);
+}
+
+void QFxFlickablePrivate::data_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxFlickablePrivate::data_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxFlickablePrivate::data_clear()
+{
+ // ###
+}
+
+
+QmlList<QObject *> *QFxFlickable::flickableData()
+{
+ Q_D(QFxFlickable);
+ return &d->data;
+}
+
+QmlList<QFxItem *> *QFxFlickable::flickableChildren()
+{
+ Q_D(QFxFlickable);
+ return d->_flick->children();
+}
+
+/*!
+ \qmlproperty bool Flickable::overShoot
+ This property holds the number of pixels the surface may overshoot the
+ Flickable's boundaries when flicked.
+
+ If overShoot is non-zero the contents can be flicked beyond the boundary
+ of the Flickable before being moved back to the boundary. This provides
+ the feeling that the edges of the view are soft, rather than a hard
+ physical boundary.
+*/
+
+/*!
+ \property QFxFlickable::overShoot
+ \brief the number of pixels the view may overshoot the boundaries when flicked.
+
+ If overShoot is non-zero the contents can be flicked beyond the boundary
+ of the view before being moved back to the boundary. This provides
+ the feeling that the edges of the view are soft, rather than a hard
+ physical boundary.
+*/
+bool QFxFlickable::overShoot() const
+{
+ Q_D(const QFxFlickable);
+ return d->overShoot;
+}
+
+void QFxFlickable::setOverShoot(bool o)
+{
+ Q_D(QFxFlickable);
+ d->overShoot = o;
+}
+
+/*!
+ \qmlproperty int Flickable::viewportWidth
+ \qmlproperty int Flickable::viewportHeight
+
+ The dimensions of the viewport (the surface controlled by Flickable). Typically this
+ should be set to the combined size of the items placed in the Flickable.
+
+ \code
+ Flickable {
+ width: 320; height: 480; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+ }
+ \endcode
+*/
+
+/*!
+ \property QFxFlickable::viewportWidth
+ \brief the width of the view.
+*/
+int QFxFlickable::viewportWidth() const
+{
+ Q_D(const QFxFlickable);
+ return d->vWidth;
+}
+
+void QFxFlickable::setViewportWidth(int w)
+{
+ Q_D(QFxFlickable);
+ if (d->vWidth == w)
+ return;
+ d->vWidth = w;
+ if (w < 0)
+ d->_flick->setWidth(width());
+ else
+ d->_flick->setWidth(w);
+ // Make sure that we're entirely in view.
+ if (d->_moveX.value() > minXExtent() || maxXExtent() > 0) {
+ d->_tl.clear();
+ d->_moveX.setValue(minXExtent());
+ } else if (d->_moveX.value() < maxXExtent()) {
+ d->_tl.clear();
+ d->_moveX.setValue(maxXExtent());
+ }
+ emit viewportWidthChanged();
+ d->updateBeginningEnd();
+}
+
+void QFxFlickable::widthChange()
+{
+ Q_D(QFxFlickable);
+ if (d->vWidth < 0) {
+ d->_flick->setWidth(width());
+ emit viewportWidthChanged();
+ d->updateBeginningEnd();
+ }
+}
+
+void QFxFlickable::heightChange()
+{
+ Q_D(QFxFlickable);
+ if (d->vHeight < 0) {
+ d->_flick->setHeight(height());
+ emit viewportHeightChanged();
+ d->updateBeginningEnd();
+ }
+}
+
+/*!
+ \property QFxFlickable::viewportHeight
+ \brief the height of the view.
+*/
+int QFxFlickable::viewportHeight() const
+{
+ Q_D(const QFxFlickable);
+ return d->vHeight;
+}
+
+void QFxFlickable::setViewportHeight(int h)
+{
+ Q_D(QFxFlickable);
+ if (d->vHeight == h)
+ return;
+ d->vHeight = h;
+ if (h < 0)
+ d->_flick->setHeight(height());
+ else
+ d->_flick->setHeight(h);
+ // Make sure that we're entirely in view.
+ if (d->_moveY.value() > minYExtent() || maxYExtent() > 0) {
+ d->_tl.clear();
+ d->_moveY.setValue(minYExtent());
+ } else if (d->_moveY.value() < maxYExtent()) {
+ d->_tl.clear();
+ d->_moveY.setValue(maxYExtent());
+ }
+ emit viewportHeightChanged();
+ d->updateBeginningEnd();
+}
+
+int QFxFlickable::vWidth() const
+{
+ Q_D(const QFxFlickable);
+ if (d->vWidth < 0)
+ return width();
+ else
+ return d->vWidth;
+}
+
+int QFxFlickable::vHeight() const
+{
+ Q_D(const QFxFlickable);
+ if (d->vHeight < 0)
+ return height();
+ else
+ return d->vHeight;
+}
+
+bool QFxFlickable::xflick() const
+{
+ return vWidth() != width();
+}
+
+bool QFxFlickable::yflick() const
+{
+ return vHeight() != height();
+}
+
+bool QFxFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height()));
+ QFxItem *grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ d->handleMouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ d->handleMousePressEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ d->handleMouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if (grabber && d->stealMouse && !grabber->keepMouseGrab())
+ grabMouse();
+
+ return d->stealMouse;
+ } else if (!d->lastPosTime.isNull()) {
+ d->lastPosTime = QTime();
+ }
+ return false;
+}
+
+bool QFxFlickable::mouseFilter(QGraphicsSceneMouseEvent *e)
+{
+ if (!isVisible())
+ return false;
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(e);
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/*!
+ \qmlproperty int Flickable::maximumFlickVelocity
+ This property holds the maximum velocity that the user can flick the view.
+*/
+
+/*!
+ \property QFxFlickable::maximumFlickVelocity
+ \brief the maximum velocity that the user can flick the view.
+*/
+int QFxFlickable::maximumFlickVelocity() const
+{
+ Q_D(const QFxFlickable);
+ return d->maxVelocity;
+}
+
+void QFxFlickable::setMaximumFlickVelocity(int v)
+{
+ Q_D(QFxFlickable);
+ if (v == d->maxVelocity)
+ return;
+ d->maxVelocity = v;
+}
+
+bool QFxFlickable::isFlicking() const
+{
+ Q_D(const QFxFlickable);
+ return d->flicked;
+}
+
+int QFxFlickable::velocityDecay() const
+{
+ Q_D(const QFxFlickable);
+ return d->velocityDecay;
+}
+
+void QFxFlickable::setVelocityDecay(int decay)
+{
+ Q_D(QFxFlickable);
+ Q_ASSERT(decay >= 0);
+ if (decay == d->velocityDecay)
+ return;
+ d->velocityDecay = decay;
+ emit velocityDecayChanged(decay);
+}
+
+bool QFxFlickable::isMoving() const
+{
+ Q_D(const QFxFlickable);
+ return d->moving;
+}
+
+void QFxFlickable::movementStarting()
+{
+ Q_D(QFxFlickable);
+ if (!d->moving) {
+ d->moving = true;
+ emit movingChanged();
+ emit movementStarted();
+ }
+}
+
+void QFxFlickable::movementEnding()
+{
+ Q_D(QFxFlickable);
+ if (d->moving) {
+ d->moving = false;
+ emit movingChanged();
+ emit movementEnded();
+ }
+ if (d->flicked) {
+ d->flicked = false;
+ emit flickingChanged();
+ emit flickEnded();
+ }
+ d->xVelocity.setValue(0);
+}
+
+void QFxFlickablePrivate::updateVelocity()
+{
+ Q_Q(QFxFlickable);
+ emit q->velocityChanged(q->xVelocity(), q->yVelocity());
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxflickable.h b/src/declarative/fx/qfxflickable.h
new file mode 100644
index 0000000..77aaf50
--- /dev/null
+++ b/src/declarative/fx/qfxflickable.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFLICKABLE_H
+#define QFXFLICKABLE_H
+
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxFlickablePrivate;
+class Q_DECLARATIVE_EXPORT QFxFlickable : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool overShoot READ overShoot WRITE setOverShoot)
+ Q_PROPERTY(int viewportWidth READ viewportWidth WRITE setViewportWidth NOTIFY viewportWidthChanged)
+ Q_PROPERTY(int viewportHeight READ viewportHeight WRITE setViewportHeight NOTIFY viewportHeightChanged)
+ Q_PROPERTY(qreal xPosition READ xPosition WRITE setXPosition NOTIFY positionChanged)
+ Q_PROPERTY(qreal yPosition READ yPosition WRITE setYPosition NOTIFY positionChanged)
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
+ Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
+ Q_PROPERTY(int velocityDecay READ velocityDecay WRITE setVelocityDecay NOTIFY velocityDecayChanged)
+ Q_PROPERTY(int maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity)
+ Q_PROPERTY(bool locked READ isLocked WRITE setLocked)
+ Q_PROPERTY(DragMode dragMode READ dragMode WRITE setDragMode)
+ Q_PROPERTY(qreal xVelocity READ xVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(qreal yVelocity READ yVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atXBeginning READ isAtXBeginning NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYBeginning READ isAtYBeginning NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(qreal pageXPosition READ pageXPosition NOTIFY pageChanged)
+ Q_PROPERTY(qreal pageYPosition READ pageYPosition NOTIFY pageChanged)
+ Q_PROPERTY(qreal pageWidth READ pageWidth NOTIFY pageChanged)
+ Q_PROPERTY(qreal pageHeight READ pageHeight NOTIFY pageChanged)
+
+ Q_PROPERTY(QmlList<QObject *>* flickableData READ flickableData)
+ Q_PROPERTY(QmlList<QFxItem *>* flickableChildren READ flickableChildren)
+ Q_CLASSINFO("DefaultProperty", "flickableData")
+
+public:
+ QFxFlickable(QFxItem *parent=0);
+ ~QFxFlickable();
+
+ QmlList<QObject *> *flickableData();
+ QmlList<QFxItem *> *flickableChildren();
+
+ bool overShoot() const;
+ void setOverShoot(bool);
+
+ int viewportWidth() const;
+ void setViewportWidth(int);
+
+ int viewportHeight() const;
+ void setViewportHeight(int);
+
+ qreal xPosition() const;
+ void setXPosition(qreal pos);
+
+ qreal yPosition() const;
+ void setYPosition(qreal pos);
+
+ bool isMoving() const;
+ bool isFlicking() const;
+
+ int velocityDecay() const;
+ void setVelocityDecay(int);
+
+ int maximumFlickVelocity() const;
+ void setMaximumFlickVelocity(int);
+
+ bool isLocked() const;
+ void setLocked(bool);
+
+ Q_ENUMS(DragMode);
+ enum DragMode { Hard, Elastic };
+ DragMode dragMode() const;
+ void setDragMode(DragMode mode);
+
+ qreal xVelocity() const;
+ qreal yVelocity() const;
+
+ bool isAtXEnd() const;
+ bool isAtXBeginning() const;
+ qreal pageXPosition() const;
+ qreal pageWidth() const;
+
+ bool isAtYEnd() const;
+ bool isAtYBeginning() const;
+ qreal pageYPosition() const;
+ qreal pageHeight() const;
+
+ QFxItem *viewport();
+
+Q_SIGNALS:
+ void viewportWidthChanged();
+ void viewportHeightChanged();
+ void positionChanged();
+ void movingChanged();
+ void flickingChanged();
+ void movementStarted();
+ void movementEnded();
+ void flickStarted();
+ void flickEnded();
+ void velocityDecayChanged(int);
+ void velocityChanged(qreal, qreal);
+ void isAtBoundaryChanged();
+ void pageChanged();
+
+protected:
+ virtual bool mouseFilter(QGraphicsSceneMouseEvent *);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+ qreal visibleX() const;
+ qreal visibleY() const;
+
+protected Q_SLOTS:
+ virtual void ticked();
+ void movementStarting();
+ void movementEnding();
+ void heightChange();
+ void widthChange();
+
+protected:
+ virtual qreal minXExtent() const;
+ virtual qreal minYExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual qreal maxYExtent() const;
+ int vWidth() const;
+ int vHeight() const;
+ virtual void viewportMoved();
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+
+ bool xflick() const;
+ bool yflick() const;
+
+protected:
+ QFxFlickable(QFxFlickablePrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxFlickable)
+ Q_DECLARE_PRIVATE(QFxFlickable)
+};
+QML_DECLARE_TYPE(QFxFlickable)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxflickable_p.h b/src/declarative/fx/qfxflickable_p.h
new file mode 100644
index 0000000..a3b1500
--- /dev/null
+++ b/src/declarative/fx/qfxflickable_p.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFLICKABLE_P_H
+#define QFXFLICKABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qdatetime.h"
+#include "qfxflickable.h"
+#include "qfxitem_p.h"
+#include "qml.h"
+#include "qmltimelinevalueproxy.h"
+#include "private/qmlanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class ElasticValue : public QAbstractAnimation {
+ Q_OBJECT
+public:
+ ElasticValue(QmlTimeLineValue &);
+ void setValue(qreal to);
+ void clear();
+
+ virtual int duration() const { return 10000; }
+
+protected:
+ virtual void updateCurrentTime(int);
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ qreal _to;
+ qreal _myValue;
+ qreal _velocity;
+ QmlTimeLineValue &_value;
+ QTime _startTime;
+};
+
+class QFxFlickablePrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxFlickable)
+
+public:
+ QFxFlickablePrivate();
+ void init();
+ virtual void fixupX();
+ virtual void fixupY();
+ void updateBeginningEnd();
+
+public:
+ QFxItem *_flick;
+ QmlTimeLineValueProxy<QFxItem> _moveX;
+ QmlTimeLineValueProxy<QFxItem> _moveY;
+ QmlTimeLine _tl;
+ int vWidth;
+ int vHeight;
+ bool overShoot;
+ bool flicked;
+ bool moving;
+ bool stealMouse;
+ bool pressed;
+ QTime lastPosTime;
+ QPointF lastPos;
+ QPointF pressPos;
+ qreal pressX;
+ qreal pressY;
+ qreal velocityX;
+ qreal velocityY;
+ QTime pressTime;
+ QmlTimeLineEvent fixupXEvent;
+ QmlTimeLineEvent fixupYEvent;
+ int maxVelocity;
+ bool locked;
+ QFxFlickable::DragMode dragMode;
+ ElasticValue elasticY;
+ ElasticValue elasticX;
+ QTime velocityTime;
+ QPointF lastFlickablePosition;
+ int velocityDecay;
+
+ void updateVelocity();
+ struct Velocity : public QmlTimeLineValue
+ {
+ Velocity(QFxFlickablePrivate *p)
+ : parent(p) {}
+ virtual void setValue(qreal v) {
+ QmlTimeLineValue::setValue(v);
+ parent->updateVelocity();
+ }
+ QFxFlickablePrivate *parent;
+ };
+ Velocity xVelocity;
+ Velocity yVelocity;
+ int vTime;
+ QmlTimeLine velocityTimeline;
+ bool atXEnd;
+ bool atXBeginning;
+ qreal pageXPosition;
+ qreal pageWidth;
+ bool atYEnd;
+ bool atYBeginning;
+ qreal pageYPosition;
+ qreal pageHeight;
+
+ void handleMousePressEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseMoveEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *);
+
+ // flickableData property
+ void data_removeAt(int);
+ int data_count() const;
+ void data_append(QObject *);
+ void data_insert(int, QObject *);
+ QObject *data_at(int) const;
+ void data_clear();
+ QML_DECLARE_LIST_PROXY(QFxFlickablePrivate, QObject *, data)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/fx/qfxflipable.cpp b/src/declarative/fx/qfxflipable.cpp
new file mode 100644
index 0000000..4c02e74
--- /dev/null
+++ b/src/declarative/fx/qfxflipable.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxflipable.h"
+#include "private/qfxitem_p.h"
+#include "qfxtransform.h"
+#include <QtDeclarative/qmlinfo.h>
+
+QML_DEFINE_TYPE(QFxFlipable,Flipable)
+
+class QFxFlipablePrivate : public QFxItemPrivate
+{
+public:
+ QFxFlipablePrivate() : current(QFxFlipable::Front), front(0), back(0), axis(0), rotation(0) {}
+
+ void setBackTransform();
+ void _q_updateAxis();
+
+ QFxFlipable::Side current;
+ QFxItem *front;
+ QFxItem *back;
+ QFxAxis *axis;
+ QFxRotation3D axisRotation;
+ qreal rotation;
+};
+
+/*!
+ \qmlclass Flipable QFxFlipable
+ \brief The Flipable item provides a surface that can be flipped.
+ \inherits Item
+
+ Flipable allows you to specify a front and a back and then flip between those sides.
+
+ \qml
+Flipable {
+ id: flipable
+ width: 40
+ height: 40
+ axis: Axis {
+ startX: 20
+ startY: 0
+ endX: 20
+ endY: 40
+ }
+ front: Image { source: "front.png" }
+ back: Image { source: "back.png" }
+ states: [
+ State {
+ name: "back"
+ SetProperty {
+ target: flipable
+ property: "rotation"
+ value: 180
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ easing: "easeInOutQuad"
+ properties: "rotation"
+ }
+ }
+ ]
+}
+ \endqml
+
+ \image flipable.gif
+*/
+
+/*!
+ \internal
+ \class QFxFlipable
+ \brief The QFxFlipable class provides a flipable surface.
+
+ \ingroup group_widgets
+
+ QFxFlipable allows you to specify a front and a back, as well as an
+ axis for the flip.
+*/
+
+QFxFlipable::QFxFlipable(QFxItem *parent)
+: QFxItem(*(new QFxFlipablePrivate), parent)
+{
+}
+
+QFxFlipable::~QFxFlipable()
+{
+}
+
+/*!
+ \qmlproperty Item Flipable::front
+ \qmlproperty Item Flipable::back
+
+ The front and back sides of the flipable.
+*/
+
+QFxItem *QFxFlipable::front()
+{
+ Q_D(const QFxFlipable);
+ return d->front;
+}
+
+void QFxFlipable::setFront(QFxItem *front)
+{
+ Q_D(QFxFlipable);
+ if (d->front) {
+ qmlInfo(this) << "front is a write-once property";
+ return;
+ }
+ d->front = front;
+ children()->append(d->front);
+ if (Back == d->current)
+ d->front->setOpacity(0.);
+}
+
+QFxItem *QFxFlipable::back()
+{
+ Q_D(const QFxFlipable);
+ return d->back;
+}
+
+void QFxFlipable::setBack(QFxItem *back)
+{
+ Q_D(QFxFlipable);
+ if (d->back) {
+ qmlInfo(this) << "back is a write-once property";
+ return;
+ }
+ d->back = back;
+ children()->append(d->back);
+ if (Front == d->current)
+ d->back->setOpacity(0.);
+}
+
+/*!
+ \qmlproperty Axis Flipable::axis
+
+ The axis to flip around. See the \l Axis documentation for more
+ information on specifying an axis.
+*/
+
+QFxAxis *QFxFlipable::axis()
+{
+ Q_D(QFxFlipable);
+ return d->axis;
+}
+
+void QFxFlipable::setAxis(QFxAxis *axis)
+{
+ Q_D(QFxFlipable);
+ //### disconnect if we are already connected?
+ if (d->axis)
+ disconnect(d->axis, SIGNAL(updated()), this, SLOT(_q_updateAxis()));
+ d->axis = axis;
+ connect(d->axis, SIGNAL(updated()), this, SLOT(_q_updateAxis()));
+ d->_q_updateAxis();
+}
+
+void QFxFlipablePrivate::_q_updateAxis()
+{
+ axisRotation.axis()->setStartX(axis->startX());
+ axisRotation.axis()->setStartY(axis->startY());
+ axisRotation.axis()->setEndX(axis->endX());
+ axisRotation.axis()->setEndY(axis->endY());
+ axisRotation.axis()->setEndZ(axis->endZ());
+}
+
+void QFxFlipablePrivate::setBackTransform()
+{
+ if (!back)
+ return;
+
+ QPointF p1(0, 0);
+ QPointF p2(1, 0);
+ QPointF p3(1, 1);
+
+ axisRotation.setAngle(180);
+ p1 = axisRotation.transform().map(p1);
+ p2 = axisRotation.transform().map(p2);
+ p3 = axisRotation.transform().map(p3);
+ axisRotation.setAngle(rotation);
+
+ QSimpleCanvas::Matrix mat;
+#ifdef QFX_RENDER_OPENGL
+ mat.translate(back->width()/2,back->height()/2, 0);
+ if (back->width() && p1.x() >= p2.x())
+ mat.rotate(180, 0, 1, 0);
+ if (back->height() && p2.y() >= p3.y())
+ mat.rotate(180, 1, 0, 0);
+ mat.translate(-back->width()/2,-back->height()/2, 0);
+#else
+ mat.translate(back->width()/2,back->height()/2);
+ if (back->width() && p1.x() >= p2.x())
+ mat.rotate(180, Qt::YAxis);
+ if (back->height() && p2.y() >= p3.y())
+ mat.rotate(180, Qt::XAxis);
+ mat.translate(-back->width()/2,-back->height()/2);
+#endif
+ back->setTransform(mat);
+}
+
+/*!
+ \qmlproperty real Flipable::rotation
+ The angle to rotate the flipable. For example, to show the back side of the flipable
+ you can set the rotation to 180.
+*/
+qreal QFxFlipable::rotation() const
+{
+ Q_D(const QFxFlipable);
+ return d->rotation;
+}
+
+void QFxFlipable::setRotation(qreal angle)
+{
+ Q_D(QFxFlipable);
+ d->rotation = angle;
+ d->axisRotation.setAngle(angle);
+ setTransform(d->axisRotation.transform());
+
+
+ int simpleAngle = int(angle) % 360;
+
+ Side newSide;
+ if (simpleAngle < 91 || simpleAngle > 270) {
+ newSide = Front;
+ } else {
+ newSide = Back;
+ }
+
+ if (newSide != d->current) {
+ d->current = newSide;
+ if (d->front)
+ d->front->setOpacity((d->current==Front)?1.:0.);
+ if (d->back) {
+ d->setBackTransform();
+ d->back->setOpacity((d->current==Back)?1.:0.);
+ }
+ emit sideChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Flipable::side
+
+ The side of the Flippable currently visible. Possible values are \c
+ Front and \c Back.
+*/
+QFxFlipable::Side QFxFlipable::side() const
+{
+ Q_D(const QFxFlipable);
+ return d->current;
+}
+
+//in some cases the user may want to specify a more complex transformation.
+//in that case, we still allow the generic use of transform.
+//(the logic here should be kept in sync with setBackTransform and setRotation)
+void QFxFlipable::transformChanged(const QSimpleCanvas::Matrix &trans)
+{
+ Q_D(QFxFlipable);
+ QPointF p1(0, 0);
+ QPointF p2(1, 0);
+ QPointF p3(1, 1);
+
+ p1 = trans.map(p1);
+ p2 = trans.map(p2);
+ p3 = trans.map(p3);
+
+ qreal cross = (p1.x() - p2.x()) * (p3.y() - p2.y()) -
+ (p1.y() - p2.y()) * (p3.x() - p2.x());
+
+ Side newSide;
+ if (cross > 0) {
+ newSide = Back;
+ } else {
+ newSide = Front;
+ }
+
+ if (newSide != d->current) {
+ d->current = newSide;
+ if (d->current==Back) {
+ QSimpleCanvas::Matrix mat;
+#ifdef QFX_RENDER_OPENGL
+ mat.translate(d->back->width()/2,d->back->height()/2, 0);
+ if (d->back->width() && p1.x() >= p2.x())
+ mat.rotate(180, 0, 1, 0);
+ if (d->back->height() && p2.y() >= p3.y())
+ mat.rotate(180, 1, 0, 0);
+ mat.translate(-d->back->width()/2,-d->back->height()/2, 0);
+#else
+ mat.translate(d->back->width()/2,d->back->height()/2);
+ if (d->back->width() && p1.x() >= p2.x())
+ mat.rotate(180, Qt::YAxis);
+ if (d->back->height() && p2.y() >= p3.y())
+ mat.rotate(180, Qt::XAxis);
+ mat.translate(-d->back->width()/2,-d->back->height()/2);
+#endif
+ d->back->setTransform(mat);
+ }
+ if (d->front)
+ d->front->setOpacity((d->current==Front)?1.:0.);
+ if (d->back)
+ d->back->setOpacity((d->current==Back)?1.:0.);
+ emit sideChanged();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qfxflipable.cpp"
diff --git a/src/declarative/fx/qfxflipable.h b/src/declarative/fx/qfxflipable.h
new file mode 100644
index 0000000..6630633
--- /dev/null
+++ b/src/declarative/fx/qfxflipable.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFLIPABLE_H
+#define QFXFLIPABLE_H
+
+#include <QtCore/QObject>
+#include <QtGui/QTransform>
+#if defined(QFX_RENDER_OPENGL)
+#include <QtGui/qmatrix4x4.h>
+#endif
+#include <QtDeclarative/qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxAxis;
+class QFxFlipablePrivate;
+class Q_DECLARATIVE_EXPORT QFxFlipable : public QFxItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(Side)
+ Q_PROPERTY(QFxItem *front READ front WRITE setFront)
+ Q_PROPERTY(QFxItem *back READ back WRITE setBack)
+ Q_PROPERTY(QFxAxis *axis READ axis WRITE setAxis)
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
+ Q_PROPERTY(Side side READ side NOTIFY sideChanged)
+public:
+ QFxFlipable(QFxItem *parent=0);
+ ~QFxFlipable();
+
+ QFxItem *front();
+ void setFront(QFxItem *);
+
+ QFxItem *back();
+ void setBack(QFxItem *);
+
+ QFxAxis *axis();
+ void setAxis(QFxAxis *axis);
+
+ qreal rotation() const;
+ void setRotation(qreal angle);
+
+ enum Side { Front, Back };
+ Side side() const;
+
+protected:
+ virtual void transformChanged(const QSimpleCanvas::Matrix &);
+
+Q_SIGNALS:
+ void sideChanged();
+
+private:
+ Q_PRIVATE_SLOT(d_func(), void _q_updateAxis())
+ Q_DISABLE_COPY(QFxFlipable)
+ Q_DECLARE_PRIVATE(QFxFlipable)
+};
+QML_DECLARE_TYPE(QFxFlipable)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXFLIPABLE_H
diff --git a/src/declarative/fx/qfxfocuspanel.cpp b/src/declarative/fx/qfxfocuspanel.cpp
new file mode 100644
index 0000000..6da8564
--- /dev/null
+++ b/src/declarative/fx/qfxfocuspanel.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxfocuspanel.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxFocusPanel,FocusPanel)
+
+/*!
+ \qmlclass FocusPanel
+ \brief The FocusPanel object explicitly creates a focus panel.
+ \inherits Item
+
+ Focus panels assist in keyboard focus handling when building QML
+ applications. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+*/
+
+/*!
+ \internal
+ \class QFxFocusPanel
+*/
+
+QFxFocusPanel::QFxFocusPanel(QFxItem *parent) :
+ QFxItem(parent)
+{
+ setOptions(IsFocusPanel);
+}
+
+QFxFocusPanel::~QFxFocusPanel()
+{
+}
+
+/*!
+ \qmlproperty bool FocusPanel::active
+
+ Sets whether the object is the active focus panel.
+*/
+
+bool QFxFocusPanel::isActive() const
+{
+ QSimpleCanvas *canvas = QSimpleCanvasItem::canvas();
+ if (canvas)
+ return canvas->activeFocusPanel() == this;
+ else
+ return false;
+}
+
+void QFxFocusPanel::setActive(bool a)
+{
+ setActiveFocusPanel(a);
+}
+
+void QFxFocusPanel::activePanelInEvent()
+{
+ QFxItem::activePanelInEvent();
+ emit activeChanged();
+}
+
+void QFxFocusPanel::activePanelOutEvent()
+{
+ QFxItem::activePanelOutEvent();
+ emit activeChanged();
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxfocuspanel.h b/src/declarative/fx/qfxfocuspanel.h
new file mode 100644
index 0000000..60f9118
--- /dev/null
+++ b/src/declarative/fx/qfxfocuspanel.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFOCUSPANEL_H
+#define QFXFOCUSPANEL_H
+
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxFocusPanel : public QFxItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
+public:
+ QFxFocusPanel(QFxItem *parent=0);
+ virtual ~QFxFocusPanel();
+
+ bool isActive() const;
+ void setActive(bool);
+
+Q_SIGNALS:
+ void activeChanged();
+
+protected:
+ virtual void activePanelInEvent();
+ virtual void activePanelOutEvent();
+
+private:
+ Q_DISABLE_COPY(QFxFocusPanel)
+};
+
+QML_DECLARE_TYPE(QFxFocusPanel)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXFOCUSPANEL_H
diff --git a/src/declarative/fx/qfxfocusrealm.cpp b/src/declarative/fx/qfxfocusrealm.cpp
new file mode 100644
index 0000000..9270bb2
--- /dev/null
+++ b/src/declarative/fx/qfxfocusrealm.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxfocusrealm.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxFocusRealm,FocusRealm)
+
+/*!
+ \qmlclass FocusRealm
+ \brief The FocusRealm object explicitly creates a focus realm.
+ \inherits Item
+
+ Focus realms assist in keyboard focus handling when building reusable QML
+ components. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+*/
+
+/*!
+ \internal
+ \class QFxFocusRealm
+*/
+
+QFxFocusRealm::QFxFocusRealm(QFxItem *parent) :
+ QFxItem(parent)
+{
+ setOptions(IsFocusRealm);
+}
+
+QFxFocusRealm::~QFxFocusRealm()
+{
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxfocusrealm.h b/src/declarative/fx/qfxfocusrealm.h
new file mode 100644
index 0000000..d2aadce
--- /dev/null
+++ b/src/declarative/fx/qfxfocusrealm.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFOCUSREALM_H
+#define QFXFOCUSREALM_H
+
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxFocusRealm : public QFxItem
+{
+ Q_OBJECT
+public:
+ QFxFocusRealm(QFxItem *parent=0);
+ virtual ~QFxFocusRealm();
+};
+
+QML_DECLARE_TYPE(QFxFocusRealm)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXFOCUSREALM_H
diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp
new file mode 100644
index 0000000..dde8fcf
--- /dev/null
+++ b/src/declarative/fx/qfxgridview.cpp
@@ -0,0 +1,1428 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxvisualitemmodel.h"
+#include "qlistmodelinterface.h"
+#include "qmlfollow.h"
+#include "private/qfxflickable_p.h"
+#include "qfxgridview.h"
+
+QT_BEGIN_NAMESPACE
+
+class QFxGridViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QFxGridViewAttached(QObject *parent)
+ : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+ ~QFxGridViewAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(QFxGridView *view READ view);
+ QFxGridView *view() { return m_view; }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged);
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged);
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ static QFxGridViewAttached *properties(QObject *obj) {
+ QFxGridViewAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QFxGridViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+signals:
+ void currentItemChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+
+public:
+ QFxGridView *m_view;
+ bool m_isCurrent;
+ bool m_delayRemove;
+
+ static QHash<QObject*, QFxGridViewAttached*> attachedProperties;
+};
+
+QHash<QObject*, QFxGridViewAttached*> QFxGridViewAttached::attachedProperties;
+
+
+//----------------------------------------------------------------------------
+
+class FxGridItem
+{
+public:
+ FxGridItem(QFxItem *i, QFxGridView *v) : item(i), view(v) {
+ attached = QFxGridViewAttached::properties(item);
+ attached->m_view = view;
+ }
+ ~FxGridItem() {}
+
+ qreal rowPos() const { return (view->flow() == QFxGridView::LeftToRight ? item->y() : item->x()); }
+ qreal colPos() const { return (view->flow() == QFxGridView::LeftToRight ? item->x() : item->y()); }
+ qreal endRowPos() const {
+ return view->flow() == QFxGridView::LeftToRight
+ ? item->y() + view->cellHeight() - 1
+ : item->x() + view->cellWidth() - 1;
+ }
+ void setPosition(qreal col, qreal row) {
+ if (view->flow() == QFxGridView::LeftToRight) {
+ item->setPos(QPointF(col, row));
+ } else {
+ item->setPos(QPointF(row, col));
+ }
+ }
+
+ QFxItem *item;
+ QFxGridView *view;
+ QFxGridViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QFxGridViewPrivate : public QFxFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QFxGridView);
+
+public:
+ QFxGridViewPrivate()
+ : model(0), currentItem(0), tmpCurrent(0), flow(QFxGridView::LeftToRight)
+ , visiblePos(0), visibleIndex(0) , currentIndex(-1)
+ , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1)
+ , highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
+ , keyPressed(false), ownModel(false), wrap(false), autoHighlight(true)
+ , fixCurrentVisibility(false) {}
+
+ void init();
+ void clear();
+ FxGridItem *createItem(int modelIndex);
+ void releaseItem(FxGridItem *item);
+ void refill(qreal from, qreal to);
+
+ void updateGrid();
+ void layout(bool removed=false);
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void updateCurrent(int modelIndex);
+
+ FxGridItem *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ qreal position() const {
+ Q_Q(const QFxGridView);
+ return flow == QFxGridView::LeftToRight ? q->yPosition() : q->xPosition();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QFxGridView);
+ if (flow == QFxGridView::LeftToRight)
+ q->setYPosition(pos);
+ else
+ q->setXPosition(pos);
+ }
+ int size() const {
+ Q_Q(const QFxGridView);
+ return flow == QFxGridView::LeftToRight ? q->height() : q->width();
+ }
+ qreal startPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
+ return pos;
+ }
+
+ qreal endPosition() const {
+ qreal pos = 0;
+ if (model && model->count())
+ pos = rowPosAt(model->count() - 1) + rowSize();
+ return pos;
+ }
+
+ bool isValid() const {
+ return model && model->count() && (!ownModel || model->delegate());
+ }
+
+ int rowSize() const {
+ return flow == QFxGridView::LeftToRight ? cellHeight : cellWidth;
+ }
+ int colSize() const {
+ return flow == QFxGridView::LeftToRight ? cellWidth : cellHeight;
+ }
+
+ qreal colPosAt(int modelIndex) const {
+ if (FxGridItem *item = visibleItem(modelIndex))
+ return item->colPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = (visibleIndex - modelIndex) % columns;
+ int col = visibleItems.first()->colPos() / colSize();
+ col = (columns - count + col) % columns;
+ return col * colSize();
+ } else {
+ int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
+ return visibleItems.last()->colPos() - count * colSize();
+ }
+ }
+ return 0;
+ }
+ qreal rowPosAt(int modelIndex) const {
+ if (FxGridItem *item = visibleItem(modelIndex))
+ return item->rowPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int firstCol = visibleItems.first()->colPos() / colSize();
+ int col = visibleIndex - modelIndex + (columns - firstCol - 1);
+ int rows = col / columns;
+ return visibleItems.first()->rowPos() - rows * rowSize();
+ } else {
+ int count = modelIndex - visibleItems.last()->index;
+ int col = visibleItems.last()->colPos() + count * colSize();
+ int rows = col / (columns * colSize());
+ return visibleItems.last()->rowPos() + rows * rowSize();
+ }
+ }
+ return 0;
+ }
+
+ // Map a model index to visibleItems list index.
+ // These may differ if removed items are still present in the visible list,
+ // e.g. doing a removal animation
+ int mapFromModel(int modelIndex) const {
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i + visibleIndex;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ qDebug() << "index" << visibleIndex << i << listItem->index;
+ for (int j = 0; j < visibleItems.count(); j++)
+ qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
+ abort();
+ }
+ }
+ }
+
+ QFxVisualItemModel *model;
+ QVariant modelVariant;
+ QList<FxGridItem*> visibleItems;
+ QHash<QFxItem*,int> unrequestedItems;
+ FxGridItem *currentItem;
+ QFxItem *tmpCurrent;
+ QFxGridView::Flow flow;
+ int visiblePos;
+ int visibleIndex;
+ int currentIndex;
+ int cellWidth;
+ int cellHeight;
+ int columns;
+ int requestedIndex;
+ QmlComponent *highlightComponent;
+ FxGridItem *highlight;
+ FxGridItem *trackedItem;
+ enum MovementReason { Other, Key, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QmlFollow *highlightXAnimator;
+ QmlFollow *highlightYAnimator;
+
+ int keyPressed : 1;
+ int ownModel : 1;
+ int wrap : 1;
+ int autoHighlight : 1;
+ int fixCurrentVisibility : 1;
+};
+
+void QFxGridViewPrivate::init()
+{
+ Q_Q(QFxGridView);
+ q->setOptions(QFxGridView::IsFocusRealm);
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(sizeChange()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(sizeChange()));
+}
+
+void QFxGridViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visiblePos = 0;
+ visibleIndex = 0;
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
+ createHighlight();
+ trackedItem = 0;
+}
+
+FxGridItem *QFxGridViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QFxGridView);
+ // create object
+ requestedIndex = modelIndex;
+ FxGridItem *listItem = 0;
+ if (QFxItem *item = model->item(modelIndex, false)) {
+ listItem = new FxGridItem(item, q);
+ listItem->index = modelIndex;
+ // complete
+ model->completeItem();
+ listItem->item->setZ(modelIndex + 1);
+ listItem->item->setParent(q->viewport());
+ }
+ requestedIndex = 0;
+ return listItem;
+}
+
+
+void QFxGridViewPrivate::releaseItem(FxGridItem *item)
+{
+ Q_Q(QFxGridView);
+ if (!item)
+ return;
+ if (trackedItem == item) {
+ QObject::disconnect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ delete item;
+}
+
+void QFxGridViewPrivate::refill(qreal from, qreal to)
+{
+ Q_Q(QFxGridView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+
+ from -= buffer;
+ to += buffer;
+ bool changed = false;
+
+ int colPos = 0;
+ int rowPos = 0;
+ int modelIndex = 0;
+ if (visibleItems.count()) {
+ rowPos = visibleItems.last()->rowPos();
+ colPos = visibleItems.last()->colPos() + colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+
+ FxGridItem *item = 0;
+ while (modelIndex < model->count() && rowPos <= to) {
+ //qDebug() << "refill: append item" << modelIndex;
+ if (!(item = createItem(modelIndex)))
+ break;
+ item->setPosition(colPos, rowPos);
+ visibleItems.append(item);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ ++modelIndex;
+ changed = true;
+ }
+
+ if (visibleItems.count()) {
+ rowPos = visibleItems.first()->rowPos();
+ colPos = visibleItems.first()->colPos() - colSize();
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ rowPos -= rowSize();
+ }
+ }
+ while (visibleIndex > 0 && rowPos + rowSize() - 1 >= from){
+ //qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+ if (!(item = createItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ item->setPosition(colPos, rowPos);
+ visibleItems.prepend(item);
+ colPos -= colSize();
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ rowPos -= rowSize();
+ }
+ changed = true;
+ }
+
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endRowPos() < from) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->rowPos() > to) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ if (changed) {
+ if (flow == QFxGridView::LeftToRight)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QFxGridViewPrivate::updateGrid()
+{
+ Q_Q(QFxGridView);
+ columns = (int)qMax((flow == QFxGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
+ if (isValid()) {
+ if (flow == QFxGridView::LeftToRight)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QFxGridViewPrivate::layout(bool removed)
+{
+ Q_Q(QFxGridView);
+ if (visibleItems.count()) {
+ qreal rowPos = visibleItems.first()->rowPos();
+ qreal colPos = visibleItems.first()->colPos();
+ if (visibleIndex % columns != 0) {
+ if (removed)
+ rowPos -= rowSize();
+ colPos = (visibleIndex % columns) * colSize();
+ visibleItems.first()->setPosition(colPos, rowPos);
+ } else if (colPos != 0) {
+ colPos = 0;
+ visibleItems.first()->setPosition(colPos, rowPos);
+ }
+ for (int i = 1; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ item->setPosition(colPos, rowPos);
+ }
+ }
+ q->refill();
+ q->trackedPositionChanged();
+ updateHighlight();
+ if (flow == QFxGridView::LeftToRight) {
+ q->setViewportHeight(endPosition() - startPosition());
+ fixupY();
+ } else {
+ q->setViewportWidth(endPosition() - startPosition());
+ fixupX();
+ }
+ updateUnrequestedPositions();
+}
+
+void QFxGridViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QFxGridView);
+ QHash<QFxItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QFxGridViewPrivate::updateUnrequestedPositions()
+{
+ QHash<QFxItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ if (flow == QFxGridView::LeftToRight) {
+ it.key()->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
+ } else {
+ it.key()->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
+ }
+ }
+}
+
+void QFxGridViewPrivate::updateTrackedItem()
+{
+ Q_Q(QFxGridView);
+ FxGridItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
+ q->trackedPositionChanged();
+ }
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QFxGridViewPrivate::createHighlight()
+{
+ Q_Q(QFxGridView);
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ delete highlight->item;
+ delete highlight;
+ highlight = 0;
+ delete highlightXAnimator;
+ delete highlightYAnimator;
+ highlightXAnimator = 0;
+ highlightYAnimator = 0;
+ }
+
+ if (!highlightComponent)
+ return;
+
+ if (currentItem) {
+ QmlContext *highlightContext = new QmlContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ highlightContext->setParent(nobj);
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (item) {
+ item->setParent(q->viewport());
+ highlight = new FxGridItem(item, q);
+ highlightXAnimator = new QmlFollow(q);
+ highlightXAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("x")));
+ highlightXAnimator->setSpring(3);
+ highlightXAnimator->setDamping(0.3);
+ highlightXAnimator->setEnabled(autoHighlight);
+ highlightYAnimator = new QmlFollow(q);
+ highlightYAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("y")));
+ highlightYAnimator->setSpring(3);
+ highlightYAnimator->setDamping(0.3);
+ highlightYAnimator->setEnabled(autoHighlight);
+ } else {
+ delete highlightContext;
+ }
+ }
+ }
+}
+
+void QFxGridViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ updateTrackedItem();
+ if (currentItem && autoHighlight && highlight) {
+ // auto-update highlight
+ highlightXAnimator->setSourceValue(currentItem->item->x());
+ highlightYAnimator->setSourceValue(currentItem->item->y());
+ highlight->item->setWidth(currentItem->item->width());
+ highlight->item->setHeight(currentItem->item->height());
+ }
+}
+
+void QFxGridViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QFxGridView);
+ if (!isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
+ updateHighlight();
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+
+ if (tmpCurrent) {
+ delete tmpCurrent;
+ tmpCurrent = 0;
+ }
+ FxGridItem *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ fixCurrentVisibility = true;
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ releaseItem(oldCurrentItem);
+}
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass GridView
+ \inherits Flickable
+ \brief The GridView item provides a grid view of items provided by a model.
+
+ The model is typically provided by a QAbstractListModel "C++ model object",
+ but can also be created directly in QML.
+
+ The items are laid out top to bottom (vertically) or left to right (horizontally)
+ and may be flicked to scroll.
+
+ The below example creates a very simple grid, using a QML model.
+
+ \image gridview.png
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 3
+
+ The model is defined as a ListModel using QML:
+ \quotefile doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
+
+ In this case ListModel is a handy way for us to test our UI. In practice
+ the model would be implemented in C++, or perhaps via a SQL data source.
+
+
+*/
+QFxGridView::QFxGridView(QFxItem *parent)
+ : QFxFlickable(*(new QFxGridViewPrivate), parent)
+{
+ Q_D(QFxGridView);
+ d->init();
+}
+
+QFxGridView::~QFxGridView()
+{
+ Q_D(QFxGridView);
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlproperty model GridView::model
+ This property holds the model providing data for the grid.
+
+ The model provides a set of data that is used to create the items
+ for the view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass, a VisualModel, or a simple list.
+*/
+QVariant QFxGridView::model() const
+{
+ Q_D(const QFxGridView);
+ return d->modelVariant;
+}
+
+void QFxGridView::setModel(const QVariant &model)
+{
+ Q_D(QFxGridView);
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QFxVisualItemModel *vim = 0;
+ if (object && (vim = qobject_cast<QFxVisualItemModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setModel(model);
+ }
+ if (d->model) {
+ if (d->currentIndex >= d->model->count() || d->currentIndex < 0)
+ setCurrentIndex(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
+ refill();
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty component GridView::delegate
+
+ The delegate provides a template describing what each item in the view should look and act like.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 0
+*/
+QmlComponent *QFxGridView::delegate() const
+{
+ Q_D(const QFxGridView);
+ return d->model ? d->model->delegate() : 0;
+}
+
+void QFxGridView::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QFxGridView);
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setDelegate(delegate);
+ d->updateCurrent(d->currentIndex);
+ refill();
+}
+
+/*!
+ \qmlproperty int GridView::currentIndex
+ \qmlproperty Item GridView::current
+
+ \c currentIndex holds the index of the current item.
+ \c current is the current item. Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QFxGridView::currentIndex() const
+{
+ Q_D(const QFxGridView);
+ return d->currentIndex;
+}
+
+void QFxGridView::setCurrentIndex(int index)
+{
+ Q_D(QFxGridView);
+ if (d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0)
+ d->updateCurrent(index);
+ else
+ d->currentIndex = index;
+}
+
+QFxItem *QFxGridView::currentItem()
+{
+ Q_D(QFxGridView);
+ if (!d->currentItem) {
+ // Always return something valid
+ if (!d->tmpCurrent)
+ d->tmpCurrent = new QFxItem(viewport());
+ return d->tmpCurrent;
+ }
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty int GridView::count
+ This property holds the number of items in the view.
+*/
+int QFxGridView::count() const
+{
+ Q_D(const QFxGridView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty component GridView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each view.
+ The geometry of the resultant component instance will be managed by the view
+ so as to stay with the current item, unless the autoHighlight property is false.
+
+ The below example demonstrates how to make a simple highlight:
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 1
+
+ \sa autoHighlight
+*/
+QmlComponent *QFxGridView::highlight() const
+{
+ Q_D(const QFxGridView);
+ return d->highlightComponent;
+}
+
+void QFxGridView::setHighlight(QmlComponent *highlight)
+{
+ Q_D(QFxGridView);
+ delete d->highlightComponent;
+ d->highlightComponent = highlight;
+ d->updateCurrent(d->currentIndex);
+}
+
+/*!
+ \qmlproperty component GridView::autoHighlight
+ This property sets whether the highlight is managed by the view.
+
+ If autoHighlight is true, the highlight will be moved smoothly
+ to follow the current item. If autoHighlight is false, the
+ highlight will not be moved by the view, and must be implemented
+ by the highlight component, for example:
+
+ \code
+ Component {
+ id: Highlight
+ Rect {
+ id: Wrapper; color: "lightsteelblue"; radius: 4; width: 320; height: 60 >
+ y: Follow { source: Wrapper.GridView.view.current.y; spring: 3; damping: 0.2 }
+ x: Follow { source: Wrapper.GridView.view.current.x; spring: 3; damping: 0.2 }
+ }
+ }
+ \endcode
+*/
+bool QFxGridView::autoHighlight() const
+{
+ Q_D(const QFxGridView);
+ return d->autoHighlight;
+}
+
+void QFxGridView::setAutoHighlight(bool autoHighlight)
+{
+ Q_D(QFxGridView);
+ d->autoHighlight = autoHighlight;
+ if (d->highlightXAnimator) {
+ d->highlightXAnimator->setEnabled(d->autoHighlight);
+ d->highlightYAnimator->setEnabled(d->autoHighlight);
+ }
+ d->updateHighlight();
+}
+
+/*!
+ \qmlproperty enumeration GridView::flow
+ This property holds the flow of the grid.
+
+ Possible values are \c LeftToRight (default) and \c TopToBottom.
+
+ If \a flow is \c LeftToRight, the view will scroll vertically.
+ If \a flow is \c TopToBottom, the view will scroll horizontally.
+*/
+QFxGridView::Flow QFxGridView::flow() const
+{
+ Q_D(const QFxGridView);
+ return d->flow;
+}
+
+void QFxGridView::setFlow(Flow flow)
+{
+ Q_D(QFxGridView);
+ if (d->flow != flow) {
+ d->flow = flow;
+ if (d->flow == LeftToRight)
+ setViewportWidth(-1);
+ else
+ setViewportHeight(-1);
+ d->clear();
+ d->updateGrid();
+ refill();
+ d->updateCurrent(d->currentIndex);
+ }
+}
+
+/*!
+ \qmlproperty bool GridView::wrap
+ This property holds whether the grid wraps key navigation
+
+ If this property is true then key presses to move off of one end of the grid will cause the
+ selection to jump to the other side.
+*/
+bool QFxGridView::isWrapEnabled() const
+{
+ Q_D(const QFxGridView);
+ return d->wrap;
+}
+
+void QFxGridView::setWrapEnabled(bool wrap)
+{
+ Q_D(QFxGridView);
+ d->wrap = wrap;
+}
+
+/*!
+ \qmlproperty int GridView::cacheBuffer
+ This property holds the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the view
+ and below the bottom of the view to cache. Setting this value can make
+ scrolling the view smoother at the expense of additional memory usage.
+*/
+
+/*!
+ \property QFxGridView::cacheBuffer
+ \brief sets the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the view
+ and below the bottom of the view to cache. Setting this value can make
+ scrolling the view smoother at the expense of additional memory usage.
+*/
+int QFxGridView::cacheBuffer() const
+{
+ Q_D(const QFxGridView);
+ return d->buffer;
+}
+
+void QFxGridView::setCacheBuffer(int buffer)
+{
+ Q_D(QFxGridView);
+ if (d->buffer != buffer) {
+ d->buffer = buffer;
+ if (isComponentComplete())
+ refill();
+ }
+}
+
+/*!
+ \qmlproperty int GridView::cellWidth
+ \qmlproperty int GridView::cellHeight
+
+ These properties holds the width and height of each cell in the grid
+
+ The default sell size is 100x100.
+*/
+int QFxGridView::cellWidth() const
+{
+ Q_D(const QFxGridView);
+ return d->cellWidth;
+}
+
+void QFxGridView::setCellWidth(int cellWidth)
+{
+ Q_D(QFxGridView);
+ if (cellWidth != d->cellWidth && cellWidth > 0) {
+ d->cellWidth = qMax(1, cellWidth);
+ d->updateGrid();
+ emit cellSizeChanged();
+ d->layout();
+ }
+}
+
+int QFxGridView::cellHeight() const
+{
+ Q_D(const QFxGridView);
+ return d->cellHeight;
+}
+
+void QFxGridView::setCellHeight(int cellHeight)
+{
+ Q_D(QFxGridView);
+ if (cellHeight != d->cellHeight && cellHeight > 0) {
+ d->cellHeight = qMax(1, cellHeight);
+ d->updateGrid();
+ emit cellSizeChanged();
+ d->layout();
+ }
+}
+
+void QFxGridView::sizeChange()
+{
+ Q_D(QFxGridView);
+ if (isComponentComplete()) {
+ d->updateGrid();
+ d->layout();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::viewportMoved()
+{
+ QFxFlickable::viewportMoved();
+ refill();
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::minYExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::TopToBottom)
+ return QFxFlickable::minYExtent();
+ return -d->startPosition();
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::maxYExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::TopToBottom)
+ return QFxFlickable::maxYExtent();
+ return -(d->endPosition() - height());
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::minXExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::LeftToRight)
+ return QFxFlickable::minXExtent();
+ return -d->startPosition();
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::maxXExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::LeftToRight)
+ return QFxFlickable::maxXExtent();
+ return -(d->endPosition() - height());
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QFxGridView);
+ if (d->model && d->model->count() && !d->locked) {
+ if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Up)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Left)) {
+ if (currentIndex() >= d->columns || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex() - d->columns;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ event->accept();
+ }
+ return;
+ } else if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Down)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Right)) {
+ if (currentIndex() < d->model->count() - d->columns || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex()+d->columns;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ event->accept();
+ }
+ return;
+ } else if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Left)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Up)) {
+ if (currentIndex() > 0 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex() - 1;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ event->accept();
+ }
+ return;
+ } else if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Right)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Down)) {
+ if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex() + 1;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ event->accept();
+ }
+ return;
+ }
+ }
+ d->moveReason = QFxGridViewPrivate::Other;
+ QFxFlickable::keyPressEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QFxGridView);
+ d->keyPressed = false;
+ QFxFlickable::keyReleaseEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::componentComplete()
+{
+ Q_D(QFxGridView);
+ QFxFlickable::componentComplete();
+ d->updateGrid();
+ if (d->currentIndex < 0)
+ d->updateCurrent(0);
+ refill();
+}
+
+void QFxGridView::trackedPositionChanged()
+{
+ Q_D(QFxGridView);
+ if (!d->trackedItem)
+ return;
+ if (!isFlicking() && !d->pressed && d->moveReason == QFxGridViewPrivate::Key) {
+ if (d->trackedItem->rowPos() < d->position()) {
+ d->setPosition(d->trackedItem->rowPos());
+ } else if (d->trackedItem->endRowPos() > d->position() + d->size()) {
+ qreal pos = d->trackedItem->endRowPos() - d->size();
+ if (d->rowSize() > d->size())
+ pos = d->trackedItem->rowPos();
+ d->setPosition(pos);
+ }
+ }
+}
+
+void QFxGridView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QFxGridView);
+ if (!d->visibleItems.count() || d->model->count() <= 1) {
+ refill();
+ d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
+ emit countChanged();
+ return;
+ }
+
+ int index = d->mapFromModel(modelIndex);
+ if (index == -1) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ // Special case of appending an item to the model.
+ index = d->visibleIndex + d->visibleItems.count();
+ } else {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+ }
+
+ // At least some of the added items will be visible
+ int insertCount = count;
+ if (index < d->visibleIndex) {
+ insertCount -= d->visibleIndex - index;
+ index = d->visibleIndex;
+ modelIndex = d->visibleIndex;
+ }
+
+ index -= d->visibleIndex;
+ int to = d->buffer+d->position()+d->size()-1;
+ int colPos, rowPos;
+ if (index < d->visibleItems.count()) {
+ colPos = d->visibleItems.at(index)->colPos();
+ rowPos = d->visibleItems.at(index)->rowPos();
+ } else {
+ // appending items to visible list
+ colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
+ rowPos = d->visibleItems.at(index-1)->rowPos();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ }
+
+ QList<FxGridItem*> added;
+ int i = 0;
+ for (; i < insertCount && rowPos + d->rowSize() - 1 <= to; ++i) {
+ int mod = (modelIndex+i) % d->columns;
+ while (mod++ < d->columns && modelIndex + i < d->model->count() && i < insertCount) {
+ FxGridItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(colPos, rowPos);
+ added.append(item);
+ colPos += d->colSize();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ ++index;
+ ++i;
+ }
+ }
+
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
+ }
+ }
+ if (i < insertCount) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index)
+ d->releaseItem(d->visibleItems.takeLast());
+ } else {
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxGridItem *listItem = d->visibleItems.at(index);
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ }
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+ d->layout();
+ emit countChanged();
+}
+
+void QFxGridView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QFxGridView);
+ int index = d->mapFromModel(modelIndex);
+ if (index == -1) {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Items removed before our visible items.
+ d->visibleIndex -= count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1)
+ listItem->index -= count;
+ }
+ }
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+ d->layout(true);
+ emit countChanged();
+ return;
+ }
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (d->visibleItems.isEmpty()) {
+ d->visibleIndex = 0;
+ d->setPosition(0);
+ refill();
+ } else {
+ // Correct the positioning of the items
+ d->layout();
+ }
+ emit countChanged();
+}
+
+void QFxGridView::destroyRemoved()
+{
+ Q_D(QFxGridView);
+ for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxGridItem *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->layout();
+}
+
+void QFxGridView::createdItem(int index, QFxItem *item)
+{
+ Q_D(QFxGridView);
+ item->setItemParent(this);
+ if (d->requestedIndex != index) {
+ item->setItemParent(this);
+ d->unrequestedItems.insert(item, index);
+ if (d->flow == QFxGridView::LeftToRight) {
+ item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
+ } else {
+ item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
+ }
+ }
+}
+
+void QFxGridView::destroyingItem(QFxItem *item)
+{
+ Q_D(QFxGridView);
+ d->unrequestedItems.remove(item);
+}
+
+
+void QFxGridView::refill()
+{
+ Q_D(QFxGridView);
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+
+QObject *QFxGridView::qmlAttachedProperties(QObject *obj)
+{
+ return QFxGridViewAttached::properties(obj);
+}
+
+QML_DEFINE_TYPE(QFxGridView,GridView)
+
+QT_END_NAMESPACE
+
+#include "qfxgridview.moc"
diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h
new file mode 100644
index 0000000..1514451
--- /dev/null
+++ b/src/declarative/fx/qfxgridview.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXGRIDVIEW_H
+#define QFXGRIDVIEW_H
+
+#include <QtDeclarative/qfxflickable.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxVisualItemModel;
+class QFxGridViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxGridView : public QFxFlickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFxGridView)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QFxItem *current READ currentItem NOTIFY currentIndexChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight)
+ Q_PROPERTY(bool autoHighlight READ autoHighlight WRITE setAutoHighlight)
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow)
+ Q_PROPERTY(bool wrap READ isWrapEnabled WRITE setWrapEnabled)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer)
+ Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellSizeChanged)
+ Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellSizeChanged)
+
+public:
+ QFxGridView(QFxItem *parent=0);
+ ~QFxGridView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QFxItem *currentItem();
+ int count() const;
+
+ QmlComponent *highlight() const;
+ void setHighlight(QmlComponent *highlight);
+
+ bool autoHighlight() const;
+ void setAutoHighlight(bool);
+
+ Q_ENUMS(Flow);
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ int cellWidth() const;
+ void setCellWidth(int);
+
+ int cellHeight() const;
+ void setCellHeight(int);
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void countChanged();
+ void currentIndexChanged();
+ void cellSizeChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void destroyRemoved();
+ void createdItem(int index, QFxItem *item);
+ void destroyingItem(QFxItem *item);
+ void sizeChange();
+
+private:
+ void refill();
+};
+
+QML_DECLARE_TYPE(QFxGridView)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/fx/qfxhighlightfilter.cpp b/src/declarative/fx/qfxhighlightfilter.cpp
new file mode 100644
index 0000000..6bf3148
--- /dev/null
+++ b/src/declarative/fx/qfxhighlightfilter.cpp
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxhighlightfilter.h"
+#include <qfxpixmap.h>
+#include <qmlcontext.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <gltexture.h>
+#include <glbasicshaders.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glsave.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFxHighlightFilterPrivate
+{
+public:
+ QFxHighlightFilterPrivate()
+ : xOffset(0), yOffset(0), tiled(false) {}
+
+ QString source;
+ QUrl url;
+ int xOffset;
+ int yOffset;
+ bool tiled;
+#if defined(QFX_RENDER_OPENGL2)
+ GLTexture tex;
+#endif
+};
+
+/*!
+ \qmlclass Highlight
+ \brief The Highlight filter adds a highlight to an item.
+ \inherits Filter
+
+ \qml
+Text {
+ id: highlighttext
+ color: "red"
+ font.size: 32
+ text: "Highlight"
+ filter: Highlight {
+ source: "pics/highlight.png"
+ xOffset: NumericAnimation {
+ running: true
+ repeat: true
+ from: 320
+ to: -320
+ duration: 2000
+ }
+ }
+}
+ \endqml
+ \image highlight.gif
+
+ Highlighting is only supported when Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Highlight filter has no effect.
+*/
+
+/*!
+ \internal
+ \class QFxHighlightFilter
+ \ingroup group_effects
+ \brief The QFxHightlightFilter class allows you to add a highlight to an item.
+*/
+
+QFxHighlightFilter::QFxHighlightFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxHighlightFilterPrivate)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ d->tex.setHorizontalWrap(GLTexture::ClampToEdge);
+ d->tex.setVerticalWrap(GLTexture::ClampToEdge);
+#endif
+}
+
+QFxHighlightFilter::~QFxHighlightFilter()
+{
+ delete d;
+ d = 0;
+}
+
+/*!
+ \qmlproperty string Highlight::source
+ This property holds the URL of the image to be used as the highlight.
+*/
+
+/*!
+ \property QFxHighlightFilter::source
+ \brief the URL of the image to be used as the highlight.
+*/
+QString QFxHighlightFilter::source() const
+{
+ return d->source;
+}
+
+void QFxHighlightFilter::imageLoaded()
+{
+ QPixmap img = QFxPixmap(d->url);
+#if defined(QFX_RENDER_OPENGL2)
+ if (!img.isNull())
+ d->tex.setImage(img.toImage());
+#endif
+ emit sourceChanged(d->source);
+ update();
+}
+
+void QFxHighlightFilter::setSource(const QString &f)
+{
+ if (d->source == f)
+ return;
+ if (!d->source.isEmpty())
+ QFxPixmap::cancelGet(d->url, this);
+ d->source = f;
+ d->url = qmlContext(this)->resolvedUrl(f);
+#if defined(QFX_RENDER_OPENGL2)
+ d->tex.clear();
+#endif
+ if (!f.isEmpty())
+ QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(imageLoaded()));
+ else
+ emit sourceChanged(d->source);
+}
+
+/*!
+ \qmlproperty bool Highlight::tiled
+ This property holds whether or not the highlight should be tiled.
+*/
+
+/*!
+ \property QFxHighlightFilter::tiled
+ \brief whether or not the highlight should be tiled.
+*/
+bool QFxHighlightFilter::tiled() const
+{
+ return d->tiled;
+}
+
+void QFxHighlightFilter::setTiled(bool t)
+{
+ if (t == d->tiled)
+ return;
+
+ d->tiled = t;
+
+#if defined(QFX_RENDER_OPENGL2)
+ if (d->tiled) {
+ d->tex.setHorizontalWrap(GLTexture::ClampToEdge);
+ d->tex.setVerticalWrap(GLTexture::ClampToEdge);
+ } else {
+ d->tex.setHorizontalWrap(GLTexture::Repeat);
+ d->tex.setVerticalWrap(GLTexture::Repeat);
+ }
+#endif
+
+ emit tiledChanged(d->tiled);
+}
+
+/*!
+ \qmlproperty int Highlight::xOffset
+ \qmlproperty int Highlight::yOffset
+ These properties hold the position of the highlight, relative to the item.
+*/
+
+/*!
+ \property QFxHighlightFilter::xOffset
+ \brief the x position of the highlight, relative to the item.
+*/
+int QFxHighlightFilter::xOffset() const
+{
+ return d->xOffset;
+}
+
+void QFxHighlightFilter::setXOffset(int x)
+{
+ if (x == d->xOffset)
+ return;
+
+ d->xOffset = x;
+ emit offsetChanged(d->xOffset, d->yOffset);
+#if defined(QFX_RENDER_OPENGL2)
+ update();
+#endif
+}
+
+/*!
+ \property QFxHighlightFilter::yOffset
+ \brief the y position of the highlight, relative to the item.
+*/
+int QFxHighlightFilter::yOffset() const
+{
+ return d->yOffset;
+}
+
+void QFxHighlightFilter::setYOffset(int y)
+{
+ if (y == d->yOffset)
+ return;
+
+ d->yOffset = y;
+ emit offsetChanged(d->xOffset, d->yOffset);
+#if defined(QFX_RENDER_OPENGL2)
+ update();
+#endif
+}
+
+void QFxHighlightFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ if (d->tex.isNull()) {
+ renderToScreen();
+ } else {
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+
+ QGLFramebufferObject *fbo = renderToFBO();
+
+ float width = r.width();
+ float height = r.height();
+
+ float texWidth = width / float(fbo->width());
+ float texHeight = height / float(fbo->height());
+
+ GLfloat vert[] = { 0, height,
+ width, height,
+ 0, 0,
+ width, 0 };
+ GLfloat texVert[] = { 0, 0,
+ texWidth, 0,
+ 0, texHeight,
+ texWidth, texHeight };
+ float texXOffset = 0;
+ float texYOffset = 0;
+
+ if (xOffset())
+ texXOffset = float(xOffset()) / float(d->tex.width());
+ if (yOffset())
+ texYOffset = float(yOffset()) / float(d->tex.height());
+
+ GLfloat addTexVert[] = { texXOffset, texYOffset,
+ 1 + texXOffset, texYOffset,
+ texXOffset, 1 + texYOffset,
+ 1 + texXOffset, 1 + texYOffset };
+
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+
+ DualTextureAddShader *shader = item->basicShaders()->dualTextureAdd();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+ shader->setOpacity(p.activeOpacity);
+
+ shader->setAttributeArray(DualTextureAddShader::Vertices, vert, 2);
+ shader->setAttributeArray(DualTextureAddShader::TextureCoords, texVert, 2);
+ shader->setAttributeArray(DualTextureAddShader::AddTextureCoords, addTexVert, 2);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(DualTextureAddShader::Vertices);
+ shader->disableAttributeArray(DualTextureAddShader::TextureCoords);
+ shader->disableAttributeArray(DualTextureAddShader::AddTextureCoords);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ releaseFBO(fbo);
+ }
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QML_DEFINE_TYPE(QFxHighlightFilter,Highlight)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxhighlightfilter.h b/src/declarative/fx/qfxhighlightfilter.h
new file mode 100644
index 0000000..19e95ac
--- /dev/null
+++ b/src/declarative/fx/qfxhighlightfilter.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXHIGHLIGHTFILTER_H
+#define QFXHIGHLIGHTFILTER_H
+
+#include <QtDeclarative/qsimplecanvasfilter.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxHighlightFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxHighlightFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(bool tiled READ tiled WRITE setTiled NOTIFY tiledChanged)
+ Q_PROPERTY(int xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged)
+ Q_PROPERTY(int yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged)
+public:
+ QFxHighlightFilter(QObject *parent=0);
+ virtual ~QFxHighlightFilter();
+
+ QString source() const;
+ void setSource(const QString &);
+
+ bool tiled() const;
+ void setTiled(bool);
+
+ int xOffset() const;
+ void setXOffset(int);
+ int yOffset() const;
+ void setYOffset(int);
+
+Q_SIGNALS:
+ void sourceChanged(const QString &);
+ void offsetChanged(int x, int y);
+ void tiledChanged(bool);
+
+private Q_SLOTS:
+ void imageLoaded();
+
+protected:
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+
+private:
+ QFxHighlightFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxHighlightFilter)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXHIGHLIGHTFILTER_H
diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp
new file mode 100644
index 0000000..22e5d97
--- /dev/null
+++ b/src/declarative/fx/qfximage.cpp
@@ -0,0 +1,1015 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfximage.h"
+#include "qfximage_p.h"
+#include <qfxperf.h>
+#if defined(QFX_RENDER_OPENGL)
+#include <glsave.h>
+#endif
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFile>
+#include <QtDeclarative/qmlengine.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QML_DEFINE_TYPE(QFxImage,Image)
+
+/*!
+ \qmlclass Image QFxImage
+ \brief The Image element allows you to add bitmaps to a scene.
+ \inherits Item
+
+ The Image element supports untransformed, stretched, grid-scaled and tiled images.
+ For an explanation of grid-scaling see the scaleGrid property description
+ or the QFxScaleGrid class description.
+
+ Examples:
+ \table
+ \row
+ \o \image declarative-qtlogo1.png
+ \o Untransformed
+ \qml
+ Image { source: "pics/qtlogo.png" }
+ \endqml
+ \row
+ \o \image declarative-qtlogo2.png
+ \o Stretched
+ \qml
+ Image { width: 160; height: 160; source: "pics/qtlogo.png" }
+ \endqml
+ \row
+ \o \image declarative-qtlogo4.png
+ \o Grid-scaled
+ \qml
+ Image { scaleGrid.left: 20; scaleGrid.right: 10
+ scaleGrid.top: 14; scaleGrid.bottom: 14
+ width: 160; height: 160; source: "pics/qtlogo.png" }
+ \endqml
+ \row
+ \o \image declarative-qtlogo3.png
+ \o Tiled
+ \qml
+ Image { tile: true; width: 160; height: 160; source: "pics/qtlogo.png" }
+ \endqml
+ \endtable
+ */
+
+/*!
+ \internal
+ \class QFxImage Image
+ \brief The QFxImage class provides an image item that you can add to a QFxView.
+
+ \ingroup group_coreitems
+
+ Example:
+ \qml
+ Image { source: "pics/star.png" }
+ \endqml
+
+ A QFxImage object can be instantiated in Qml using the tag \l Image.
+*/
+
+QFxImage::QFxImage(QFxItem *parent)
+ : QFxItem(*(new QFxImagePrivate), parent)
+{
+ setOptions(SimpleItem | HasContents, true);
+}
+
+QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ setOptions(SimpleItem | HasContents, true);
+}
+
+QFxImage::~QFxImage()
+{
+ Q_D(const QFxImage);
+ if (d->sciReply)
+ d->sciReply->deleteLater();
+}
+
+/*!
+ \property QFxImage::pixmap
+ \brief the image displayed in this item.
+
+ This property contains the image currently being displayed by this item,
+ which may be an empty pixmap if nothing is currently displayed. If this
+ property is set, the source property will be unset. This property is intended
+ to be used only in C++, not in QML.
+*/
+QPixmap QFxImage::pixmap() const
+{
+ Q_D(const QFxImage);
+ return d->_pix;
+}
+
+void QFxImage::setPixmap(const QPixmap &pix)
+{
+ Q_D(QFxImage);
+ d->url = QUrl();
+ d->_pix = pix;
+ d->_opaque=false;
+
+ setImplicitWidth(d->_pix.width());
+ setImplicitHeight(d->_pix.height());
+
+#if defined(QFX_RENDER_OPENGL)
+ d->_texDirty = true;
+ d->_tex.clear();
+#endif
+ update();
+}
+
+/*!
+ \qmlproperty int Image::scaleGrid.left
+ \qmlproperty int Image::scaleGrid.right
+ \qmlproperty int Image::scaleGrid.top
+ \qmlproperty int Image::scaleGrid.bottom
+
+ \target ImagexmlpropertiesscaleGrid
+
+ A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below:
+
+ \image declarative-scalegrid.png
+
+ When the image is scaled:
+ \list
+ \i the corners (sections 1, 3, 7, and 9) are not scaled at all
+ \i the middle (section 5) is scaled both horizontally and vertically
+ \i sections 2 and 8 are scaled horizontally
+ \i sections 4 and 6 are scaled vertically
+ \endlist
+
+ Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c scaleGrid.bottom="10" sets the bottom scale grid line 10 pixels up from the bottom of the image.
+
+ A scale grid can also be specified using a
+ \l {Image::source}{.sci file}.
+*/
+QFxScaleGrid *QFxImage::scaleGrid()
+{
+ Q_D(QFxImage);
+ return d->scaleGrid();
+}
+
+/*!
+ \qmlproperty bool Image::tile
+
+ Set this property to enable image tiling. Normally the Image element scales the
+ bitmap file to its size. If tiling is enabled, the bitmap is repeated as a set
+ of unscaled tiles, clipped to the size of the Image.
+
+ \qml
+ Item {
+ Image { source: "tile.png" }
+ Image { x: 80; width: 100; height: 100; source: "tile.png" }
+ Image { x: 190; width: 100; height: 100; tile: true; source: "tile.png" }
+ }
+ \endqml
+ \image declarative-image_tile.png
+
+ If both tiling and the scaleGrid are set, tiling takes precedence.
+*/
+bool QFxImage::isTiled() const
+{
+ Q_D(const QFxImage);
+ return d->_tiled;
+}
+
+void QFxImage::setTiled(bool tile)
+{
+ Q_D(QFxImage);
+ d->_tiled = tile;
+}
+
+/*!
+ \qmlproperty bool Image::opaque
+
+ Set this property if you know that the image is opaque to give your
+ application a significant performance boost.
+
+ \note
+ This is a performance hint to Qt Declarative. Unfortunately whether or not an image
+ is opaque is not automatically detected. Setting this property to true when
+ the image is not opaque will lead to drawing artifacts. However, leaving it as
+ false will always work correctly - although possibly not at maximum performance.
+ */
+
+/*!
+ \property QFxImage::opaque
+ \brief whether the image is opaque (non-transparent).
+
+ This property is provided purely for the purpose of optimization. An opaque
+ image can be optimized more than a non-opaque one.
+*/
+bool QFxImage::isOpaque() const
+{
+ Q_D(const QFxImage);
+ return d->_opaque;
+}
+
+void QFxImage::setOpaque(bool o)
+{
+ Q_D(QFxImage);
+ if (o == d->_opaque)
+ return;
+ d->_opaque = o;
+ update();
+}
+
+void QFxImage::componentComplete()
+{
+ QFxItem::componentComplete();
+}
+
+/*!
+ \property QFxImage::scaleGrid
+ \brief the 3x3 grid used to scale an image, excluding the corners.
+*/
+
+/*!
+ \qmlproperty bool Image::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the Image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+ */
+
+/*!
+ \property QFxImage::smooth
+ \brief whether the image is smoothly transformed.
+
+ This property is provided purely for the purpose of optimization. Turning
+ smooth transforms off is faster, but looks worse; turning smooth
+ transformations on is slower, but looks better.
+
+ By default smooth transformations are off.
+*/
+bool QFxImage::smoothTransform() const
+{
+ Q_D(const QFxImage);
+ return d->_smooth;
+}
+
+void QFxImage::setSmoothTransform(bool s)
+{
+ Q_D(QFxImage);
+ if (d->_smooth == s)
+ return;
+ d->_smooth = s;
+ update();
+}
+
+void QFxImage::dump(int depth)
+{
+ Q_D(QFxImage);
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "URL:" << d->url;
+ QFxItem::dump(depth);
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxImage::paintContents(QPainter &p)
+{
+ Q_D(QFxImage);
+ if (d->_pix.isNull())
+ return;
+
+ QPainter::RenderHints oldHints = p.renderHints();
+ if (d->_smooth)
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->_smooth);
+
+ QPixmap pix = d->_pix;
+
+ if (d->_tiled) {
+ p.save();
+ p.setClipRect(0, 0, width(), height(), Qt::IntersectClip);
+ QRect me = QRect(0, 0, width(), height());
+
+ int pw = pix.width();
+ int ph = pix.height();
+ int yy = 0;
+
+ while(yy < height()) {
+ int xx = 0;
+ while(xx < width()) {
+ p.drawPixmap(xx, yy, pix);
+ xx += pw;
+ }
+ yy += ph;
+ }
+
+ p.restore();
+ } else if (!d->_scaleGrid || d->_scaleGrid->isNull()) {
+ if (width() != pix.width() || height() != pix.height()) {
+ QTransform scale;
+ scale.scale(width() / qreal(pix.width()),
+ height() / qreal(pix.height()));
+ QTransform old = p.transform();
+ p.setWorldTransform(scale * old);
+ p.drawPixmap(0, 0, pix);
+ p.setWorldTransform(old);
+ } else {
+ p.drawPixmap(0, 0, pix);
+ }
+ } else {
+ int sgl = d->_scaleGrid->left();
+ int sgr = d->_scaleGrid->right();
+ int sgt = d->_scaleGrid->top();
+ int sgb = d->_scaleGrid->bottom();
+
+ int w = width();
+ int h = height();
+ if (sgt + sgb > h)
+ sgt = sgb = h/2;
+ if (sgl + sgr > w)
+ sgl = sgr = w/2;
+
+ const int xSide = sgl + sgr;
+ const int ySide = sgt + sgb;
+
+ // Upper left
+ if (sgt && sgl)
+ p.drawPixmap(QRect(0, 0, sgl, sgt), pix, QRect(0, 0, sgl, sgt));
+ // Upper middle
+ if (pix.width() - xSide && sgt)
+ p.drawPixmap(QRect(sgl, 0, w - xSide, sgt), pix,
+ QRect(sgl, 0, pix.width() - xSide, sgt));
+ // Upper right
+ if (sgt && pix.width() - sgr)
+ p.drawPixmap(QPoint(w-sgr, 0), pix,
+ QRect(pix.width()-sgr, 0, sgr, sgt));
+ // Middle left
+ if (sgl && pix.height() - ySide)
+ p.drawPixmap(QRect(0, sgt, sgl, h - ySide), pix,
+ QRect(0, sgt, sgl, pix.height() - ySide));
+
+ // Middle
+ if (pix.width() - xSide && pix.height() - ySide)
+ p.drawPixmap(QRect(sgl, sgt, w - xSide, h - ySide),
+ pix,
+ QRect(sgl, sgt, pix.width() - xSide, pix.height() - ySide));
+ // Middle right
+ if (sgr && pix.height() - ySide)
+ p.drawPixmap(QRect(w-sgr, sgt, sgr, h - ySide), pix,
+ QRect(pix.width()-sgr, sgt, sgr, pix.height() - ySide));
+ // Lower left
+ if (sgl && sgr)
+ p.drawPixmap(QPoint(0, h - sgb), pix,
+ QRect(0, pix.height() - sgb, sgl, sgb));
+ // Lower Middle
+ if (pix.width() - xSide && sgb)
+ p.drawPixmap(QRect(sgl, h - sgb, w - xSide, sgb), pix,
+ QRect(sgl, pix.height() - sgb, pix.width() - xSide, sgb));
+ // Lower Right
+ if (sgr && sgb)
+ p.drawPixmap(QPoint(w-sgr, h - sgb), pix,
+ QRect(pix.width()-sgr, pix.height() - sgb, sgr, sgb));
+ }
+
+ if (d->_smooth)
+ p.setRenderHints(oldHints);
+}
+#elif defined(QFX_RENDER_OPENGL)
+uint QFxImage::glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count)
+{
+ Q_D(QFxImage);
+
+ if (d->_pix.isNull() || (d->_scaleGrid && !d->_scaleGrid->isNull()))
+ return 0;
+
+ if (count < 8)
+ return 8;
+
+ d->checkDirty();
+
+ float widthV = width();
+ float heightV = height();
+
+ vertices[0] = 0; vertices[1] = heightV;
+ vertices[2] = widthV; vertices[3] = heightV;
+ vertices[4] = 0; vertices[5] = 0;
+ vertices[6] = widthV; vertices[7] = 0;
+
+ *texture = &d->_tex;
+
+ if (d->_tiled) {
+ float tileWidth = widthV / d->_pix.width();
+ float tileHeight = heightV / d->_pix.height();
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = tileWidth; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = tileHeight;
+ texVertices[6] = tileWidth; texVertices[7] = tileHeight;
+ } else {
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = 1; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = 1;
+ texVertices[6] = 1; texVertices[7] = 1;
+ }
+
+ return 8;
+}
+
+void QFxImagePrivate::checkDirty()
+{
+ if (_texDirty && !_pix.isNull()) {
+ _tex.setImage(_pix.toImage());
+ _tex.setHorizontalWrap(GLTexture::Repeat);
+ _tex.setVerticalWrap(GLTexture::Repeat);
+ }
+ _texDirty = false;
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+void QFxImage::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxImage);
+ if (d->_pix.isNull())
+ return;
+
+ QGLShaderProgram *shader = p.useTextureShader();
+
+ bool restoreBlend = false;
+ if (isOpaque() && p.activeOpacity == 1) {
+ glDisable(GL_BLEND);
+ restoreBlend = true;
+ }
+
+ if (d->_tiled || (!d->_scaleGrid || d->_scaleGrid->isNull())) {
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+ GLTexture *tex = 0;
+
+ QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8);
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, tex->texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+
+ } else {
+ d->checkDirty();
+
+ float imgWidth = d->_pix.width();
+ float imgHeight = d->_pix.height();
+ if (!imgWidth || !imgHeight) {
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+ return;
+ }
+
+ float widthV = width();
+ float heightV = height();
+
+ float texleft = 0;
+ float texright = 1;
+ float textop = 1;
+ float texbottom = 0;
+ float imgleft = 0;
+ float imgright = widthV;
+ float imgtop = 0;
+ float imgbottom = heightV;
+
+ const int sgl = d->_scaleGrid->left();
+ const int sgr = d->_scaleGrid->right();
+ const int sgt = d->_scaleGrid->top();
+ const int sgb = d->_scaleGrid->bottom();
+
+ if (sgl) {
+ texleft = float(sgl) / imgWidth;
+ imgleft = sgl;
+ }
+ if (sgr) {
+ texright = 1. - float(sgr) / imgWidth;
+ imgright = widthV - sgr;
+ }
+ if (sgt) {
+ textop = 1. - float(sgb) / imgHeight;
+ imgtop = sgt;
+ }
+ if (sgb) {
+ texbottom = float(sgt) / imgHeight;
+ imgbottom = heightV - sgb;
+ }
+
+ float vert1[] = { 0, 0,
+ 0, imgtop,
+ imgleft, 0,
+ imgleft, imgtop,
+ imgright, 0,
+ imgright, imgtop,
+ widthV, 0,
+ widthV, imgtop };
+ float tex1[] = { 0, 1,
+ 0, textop,
+ texleft, 1,
+ texleft, textop,
+ texright, 1,
+ texright, textop,
+ 1, 1,
+ 1, textop };
+ float vert2[] = { 0, imgtop,
+ 0, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { 0, imgbottom,
+ 0, heightV,
+ imgleft, imgbottom,
+ imgleft, heightV,
+ imgright, imgbottom,
+ imgright, heightV,
+ widthV, imgbottom,
+ widthV, heightV };
+ float tex3[] = { 0, texbottom,
+ 0, 0,
+ texleft, texbottom,
+ texleft, 0,
+ texright, texbottom,
+ texright, 0,
+ 1, texbottom,
+ 1, 0 };
+
+ glBindTexture(GL_TEXTURE_2D, d->_tex.texture());
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ }
+
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+}
+#elif defined(QFX_RENDER_OPENGL1)
+void QFxImage::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxImage);
+ if (d->_pix.isNull())
+ return;
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(p.activeTransform.data());
+
+ bool restoreBlend = false;
+ if (isOpaque() && p.activeOpacity == 1) {
+ glDisable(GL_BLEND);
+ restoreBlend = true;
+ }
+
+ glEnable(GL_TEXTURE_2D);
+ if (p.activeOpacity == 1.) {
+ GLint i = GL_REPLACE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ } else {
+ GLint i = GL_MODULATE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ glColor4f(1, 1, 1, p.activeOpacity);
+ }
+
+ if (d->_tiled || !d->_scaleGrid || d->_scaleGrid->isNull()) {
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+ GLTexture *tex = 0;
+
+ QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8);
+
+ glBindTexture(GL_TEXTURE_2D, tex->texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texVertices);
+
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+
+ } else {
+ d->checkDirty();
+
+ float imgWidth = d->_pix.width();
+ float imgHeight = d->_pix.height();
+ if (!imgWidth || !imgHeight) {
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+ return;
+ }
+
+ float widthV = width();
+ float heightV = height();
+
+ float texleft = 0;
+ float texright = 1;
+ float textop = 1;
+ float texbottom = 0;
+ float imgleft = 0;
+ float imgright = widthV;
+ float imgtop = 0;
+ float imgbottom = heightV;
+
+ const int sgl = d->_scaleGrid->left();
+ const int sgr = d->_scaleGrid->right();
+ const int sgt = d->_scaleGrid->top();
+ const int sgb = d->_scaleGrid->bottom();
+
+ if (sgl) {
+ texleft = float(sgl) / imgWidth;
+ imgleft = sgl;
+ }
+ if (sgr) {
+ texright = 1. - float(sgr) / imgWidth;
+ imgright = widthV - sgr;
+ }
+ if (sgt) {
+ textop = 1. - float(sgb) / imgHeight;
+ imgtop = sgt;
+ }
+ if (sgb) {
+ texbottom = float(sgt) / imgHeight;
+ imgbottom = heightV - sgb;
+ }
+
+ float vert1[] = { 0, 0,
+ 0, imgtop,
+ imgleft, 0,
+ imgleft, imgtop,
+ imgright, 0,
+ imgright, imgtop,
+ widthV, 0,
+ widthV, imgtop };
+ float tex1[] = { 0, 1,
+ 0, textop,
+ texleft, 1,
+ texleft, textop,
+ texright, 1,
+ texright, textop,
+ 1, 1,
+ 1, textop };
+ float vert2[] = { 0, imgtop,
+ 0, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { 0, imgbottom,
+ 0, heightV,
+ imgleft, imgbottom,
+ imgleft, heightV,
+ imgright, imgbottom,
+ imgright, heightV,
+ widthV, imgbottom,
+ widthV, heightV };
+ float tex3[] = { 0, texbottom,
+ 0, 0,
+ texleft, texbottom,
+ texleft, 0,
+ texright, texbottom,
+ texright, 0,
+ 1, texbottom,
+ 1, 0 };
+
+ glBindTexture(GL_TEXTURE_2D, d->_tex.texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert1);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ glVertexPointer(2, GL_FLOAT, 0, vert2);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ glVertexPointer(2, GL_FLOAT, 0, vert3);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex3);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+ }
+
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+}
+#endif
+
+#endif
+
+QString QFxImage::propertyInfo() const
+{
+ Q_D(const QFxImage);
+ return d->url.toString();
+}
+
+/*!
+ \qmlproperty enum Image::status
+
+ This property holds the status of image loading. It can be one of:
+ \list
+ \o Idle - no image has been set, or the image has been loaded
+ \o Loading - the images is currently being loaded
+ \o Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
+QFxImage::Status QFxImage::status() const
+{
+ Q_D(const QFxImage);
+ return d->status;
+}
+
+/*!
+ \qmlproperty real Image::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+qreal QFxImage::progress() const
+{
+ Q_D(const QFxImage);
+ return d->progress;
+}
+
+/*!
+ \qmlproperty string Image::source
+
+ Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
+
+ It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies
+ \list
+ \i the grid lines describing a \l {Image::scaleGrid.left}{scale grid}.
+ \i an image file.
+ \endlist
+
+ The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png:
+ \code
+ gridLeft: 10
+ gridTop: 10
+ gridBottom: 10
+ gridRight: 10
+ imageFile: picture.png
+ \endcode
+
+ The URL may be absolute, or relative to the URL of the component.
+*/
+
+/*!
+ \property QFxImage::source
+ \brief the url of the image to be displayed in this item.
+
+ The content specified can be of any image type loadable by QImage. Alternatively,
+ you can specify an sci format file, which specifies both an image and it's scale grid.
+*/
+QString QFxImage::source() const
+{
+ Q_D(const QFxImage);
+ return d->source;
+}
+
+void QFxImage::setSource(const QString &url)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::PixmapLoad> perf;
+#endif
+ Q_D(QFxImage);
+ if (url == d->source)
+ return;
+
+ if (d->sciReply) {
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ }
+
+ if (!d->url.isEmpty())
+ QFxPixmap::cancelGet(d->url, this);
+ if (!d->sciurl.isEmpty())
+ QFxPixmap::cancelGet(d->sciurl, this);
+
+ d->source = url;
+ d->url = qmlContext(this)->resolvedUrl(url);
+ d->sciurl = QUrl();
+ if (d->progress != 0.0) {
+ d->progress = 0.0;
+ emit progressChanged(d->progress);
+ }
+
+ if (url.isEmpty()) {
+ setPixmap(QPixmap());
+ d->status = Idle;
+ d->progress = 1.0;
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+#if defined(QFX_RENDER_OPENGL)
+ d->_texDirty = true;
+ d->_tex.clear();
+#endif
+ emit statusChanged(d->status);
+ emit sourceChanged(d->source);
+ emit progressChanged(1.0);
+ update();
+ } else {
+ d->status = Loading;
+ if (d->url.path().endsWith(QLatin1String(".sci"))) {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ if (d->url.scheme() == QLatin1String("file")) {
+ QFile file(d->url.toLocalFile());
+ file.open(QIODevice::ReadOnly);
+ setGridScaledImage(QFxGridScaledImage(&file));
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->sciReply, SIGNAL(finished()),
+ this, SLOT(sciRequestFinished()));
+ }
+ } else {
+ d->reply = QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(requestFinished()));
+ if (d->reply) {
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ }
+ }
+ }
+
+ emit statusChanged(d->status);
+}
+
+void QFxImage::requestFinished()
+{
+ Q_D(QFxImage);
+ if (d->url.path().endsWith(QLatin1String(".sci"))) {
+ d->_pix = QFxPixmap(d->sciurl);
+ } else {
+ if (d->reply) {
+ disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ if (d->reply->error() != QNetworkReply::NoError)
+ d->status = Error;
+ }
+ d->_pix = QFxPixmap(d->url);
+ setOptions(QFxImage::SimpleItem, true);
+ }
+ setImplicitWidth(d->_pix.width());
+ setImplicitHeight(d->_pix.height());
+
+ if (d->status == Loading)
+ d->status = Idle;
+ d->progress = 1.0;
+#if defined(QFX_RENDER_OPENGL)
+ d->_texDirty = true;
+ d->_tex.clear();
+#endif
+ emit statusChanged(d->status);
+ emit sourceChanged(d->source);
+ emit progressChanged(1.0);
+ update();
+}
+
+void QFxImage::sciRequestFinished()
+{
+ Q_D(QFxImage);
+ if (d->sciReply->error() != QNetworkReply::NoError) {
+ d->status = Error;
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ emit statusChanged(d->status);
+ } else {
+ QFxGridScaledImage sci(d->sciReply);
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ setGridScaledImage(sci);
+ }
+}
+
+void QFxImage::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QFxImage);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
+
+void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci)
+{
+ Q_D(QFxImage);
+ if (!sci.isValid()) {
+ d->status = Error;
+ emit statusChanged(d->status);
+ } else {
+ d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
+ d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, this, SLOT(requestFinished()));
+ if (d->reply) {
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ }
+ QFxScaleGrid *sg = scaleGrid();
+ sg->setTop(sci.gridTop());
+ sg->setBottom(sci.gridBottom());
+ sg->setLeft(sci.gridLeft());
+ sg->setRight(sci.gridRight());
+ setOptions(QFxImage::SimpleItem, false);
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h
new file mode 100644
index 0000000..4d5f134
--- /dev/null
+++ b/src/declarative/fx/qfximage.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGE_H
+#define QFXIMAGE_H
+
+#include <QtDeclarative/qfxitem.h>
+#include <QtNetwork/qnetworkreply.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxImagePrivate;
+class Q_DECLARATIVE_EXPORT QFxImage : public QFxItem
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+
+ Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid)
+ Q_PROPERTY(bool tile READ isTiled WRITE setTiled)
+ Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap DESIGNABLE false)
+ Q_PROPERTY(bool opaque READ isOpaque WRITE setOpaque)
+ Q_PROPERTY(bool smooth READ smoothTransform WRITE setSmoothTransform)
+public:
+ QFxImage(QFxItem *parent=0);
+ ~QFxImage();
+
+ QFxScaleGrid *scaleGrid();
+
+ bool isTiled() const;
+ void setTiled(bool tile);
+
+ QPixmap pixmap() const;
+ void setPixmap(const QPixmap &);
+
+ bool isOpaque() const;
+ void setOpaque(bool);
+
+ bool smoothTransform() const;
+ void setSmoothTransform(bool);
+
+ enum Status { Idle, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ QString source() const;
+ virtual void setSource(const QString &url);
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#elif defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+ uint glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count);
+#endif
+
+Q_SIGNALS:
+ void sourceChanged(const QString &);
+ void statusChanged(Status);
+ void progressChanged(qreal progress);
+
+protected:
+ QFxImage(QFxImagePrivate &dd, QFxItem *parent);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void requestFinished();
+ void sciRequestFinished();
+ void requestProgress(qint64,qint64);
+
+private:
+ Q_DISABLE_COPY(QFxImage)
+ Q_DECLARE_PRIVATE(QFxImage)
+ void setGridScaledImage(const QFxGridScaledImage& sci);
+};
+QML_DECLARE_TYPE(QFxImage)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXIMAGE_H
diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h
new file mode 100644
index 0000000..b3cccf9
--- /dev/null
+++ b/src/declarative/fx/qfximage_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGE_P_H
+#define QFXIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxitem_p.h"
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QSvgRenderer;
+class QWebPage;
+class QNetworkReply;
+class QIODevice;
+
+class QFxImagePrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxImage)
+
+public:
+ QFxImagePrivate()
+ : _scaleGrid(0), _tiled(false), _smooth(false), _opaque(false),
+#if defined(QFX_RENDER_OPENGL)
+ _texDirty(true),
+#endif
+ status(QFxImage::Idle), sciReply(0), progress(0.0)
+ {
+ }
+
+ ~QFxImagePrivate()
+ {
+ delete _scaleGrid;
+ }
+
+ void setContent(QIODevice* dev, const QString &url);
+
+ QFxScaleGrid *scaleGrid()
+ {
+ if (!_scaleGrid)
+ _scaleGrid = new QFxScaleGrid;
+ return _scaleGrid;
+ }
+
+ QFxScaleGrid *_scaleGrid;
+ QPixmap _pix;
+ bool _tiled : 1;
+ bool _smooth : 1;
+ bool _opaque : 1;
+#if defined(QFX_RENDER_OPENGL)
+ void checkDirty();
+ bool _texDirty;
+ GLTexture _tex;
+#endif
+
+ QFxImage::Status status;
+ QString source;
+ QUrl url;
+ QUrl sciurl;
+ QNetworkReply *sciReply;
+ QPointer<QNetworkReply> reply;
+ qreal progress;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXIMAGE_P_H
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
new file mode 100644
index 0000000..7129757
--- /dev/null
+++ b/src/declarative/fx/qfxitem.cpp
@@ -0,0 +1,2100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QGraphicsSceneMouseEvent>
+#include <QtScript/qscriptengine.h>
+#include <qfxperf.h>
+
+#include "qmlengine.h"
+#include "qmlstate.h"
+#include "qlistmodelinterface.h"
+#include "qfxanchors_p.h"
+
+#include "qfxtransform.h"
+#include "qfxscalegrid.h"
+#include "qfxview.h"
+#include "qmlstategroup.h"
+
+#include "qfxitem_p.h"
+#include "qfxitem.h"
+#include "qfxevents_p.h"
+#include <qsimplecanvasfilter.h>
+#include <qmlcomponent.h>
+
+
+QT_BEGIN_NAMESPACE
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+QML_DEFINE_NOCREATE_TYPE(QFxContents)
+QML_DEFINE_TYPE(QFxItem,Item)
+QML_DEFINE_NOCREATE_TYPE(QSimpleCanvasFilter)
+
+/*!
+ \group group_animation
+ \title Animation
+*/
+
+/*!
+ \group group_coreitems
+ \title Basic Items
+*/
+
+/*!
+ \group group_effects
+ \title Effects
+*/
+
+/*!
+ \group group_layouts
+ \title Layouts
+*/
+
+/*!
+ \group group_states
+ \title States and Transitions
+*/
+
+/*!
+ \group group_utility
+ \title Utility
+*/
+
+/*!
+ \group group_views
+ \title Views
+*/
+
+/*!
+ \group group_widgets
+ \title Widgets
+*/
+
+/*!
+ \internal
+ \class QFxContents
+ \ingroup group_utility
+ \brief The QFxContents class gives access to the height and width of an item's contents.
+
+*/
+
+QFxContents::QFxContents() : _height(0), _width(0)
+{
+}
+
+/*!
+ \property QFxContents::height
+ \brief The height of the contents.
+*/
+int QFxContents::height() const
+{
+ return _height;
+}
+
+/*!
+ \property QFxContents::width
+ \brief The width of the contents.
+*/
+int QFxContents::width() const
+{
+ return _width;
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QFxContents::calcHeight()
+{
+ int oldheight = _height;
+
+ int top = INT_MAX;
+ int bottom = 0;
+
+ const QList<QSimpleCanvasItem *> &children = _item->QSimpleCanvasItem::children();
+ for (int i = 0; i < children.count(); ++i) {
+ const QSimpleCanvasItem *child = children.at(i);
+ int y = int(child->y());
+ if (y + child->height() > bottom)
+ bottom = y + child->height();
+ if (y < top)
+ top = y;
+ }
+ _height = bottom - top;
+
+ if (_height != oldheight)
+ emit heightChanged();
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QFxContents::calcWidth()
+{
+ int oldwidth = _width;
+
+ int left = INT_MAX;
+ int right = 0;
+ const QList<QSimpleCanvasItem *> &children = _item->QSimpleCanvasItem::children();
+ for (int i = 0; i < children.count(); ++i) {
+ const QSimpleCanvasItem *child = children.at(i);
+ int x = int(child->x());
+ if (x + child->width() > right)
+ right = x + child->width();
+ if (x < left)
+ left = x;
+ }
+ _width = right - left;
+
+ if (_width != oldwidth)
+ emit widthChanged();
+}
+
+void QFxContents::setItem(QFxItem *item)
+{
+ _item = item;
+
+ const QList<QSimpleCanvasItem *> &children = _item->QSimpleCanvasItem::children();
+ for (int i = 0; i < children.count(); ++i) {
+ const QSimpleCanvasItem *child = children.at(i);
+ connect(child, SIGNAL(heightChanged()), this, SLOT(calcHeight()));
+ connect(child, SIGNAL(topChanged()), this, SLOT(calcHeight()));
+ connect(child, SIGNAL(widthChanged()), this, SLOT(calcWidth()));
+ connect(child, SIGNAL(leftChanged()), this, SLOT(calcWidth()));
+ }
+
+ calcHeight();
+ calcWidth();
+}
+
+/*!
+ \qmlclass Item QFxItem
+ \brief The Item is the most basic of all visual items in QML.
+ */
+
+/*!
+ \class QFxItem Item
+ \brief The QFxItem class is a generic QFxView item. It is the base class for all other view items.
+
+ \qmltext
+ All visual items in Qt Declarative inherit from QFxItem. Although QFxItem
+ has no visual appearance, it defines all the properties that are
+ common across visual items - like the x and y position, and the
+ width and height.
+
+ QFxItem is also useful for grouping items together.
+
+ \qml
+ Item {
+ Image {
+ file: "tile.png"
+ }
+ Image {
+ x: 80
+ width: 100
+ height: 100
+ file: "tile.png"
+ }
+ Image {
+ x: 190
+ width: 100
+ height: 100
+ tile: true
+ file: "tile.png"
+ }
+ }
+ \endqml
+ \endqmltext
+
+ \ingroup group_coreitems
+*/
+
+/*!
+ \property QFxItem::activeFocus
+ This property indicates whether the item has the active focus.
+ */
+
+/*!
+ \fn void QFxItem::activeFocusChanged()
+
+ This signal is emitted when this item gains active focus.
+*/
+
+/*!
+ \fn void QFxItem::baselineOffsetChanged()
+
+ This signal is emitted when the baseline offset of the item
+ is changed.
+*/
+
+/*!
+ \fn void QFxItem::leftChanged()
+
+ This signal is emitted when the left coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::topChanged()
+
+ This signal is emitted when the top coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::widthChanged()
+
+ This signal is emitted when the width of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::heightChanged()
+
+ This signal is emitted when the height of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::hcenterChanged()
+
+ This signal is emitted when the horizontal center coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::vcenterChanged()
+
+ This signal is emitted when the vertical center coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::scaleChanged()
+
+ This signal is emitted when the scale of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::stateChanged(const QString &state)
+
+ This signal is emitted when the \a state of the item changes.
+
+ \sa states-transitions
+*/
+
+/*!
+ \qmlsignal Item::onKeyPress(event)
+
+ This handler is called when a key is pressed.
+
+ The key event is available via the KeyEvent \a event.
+
+ \qml
+ Item {
+ onKeyPress: { if (event.key == Qt.Key_Enter) state='Enter' }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal Item::onKeyRelease(event)
+
+ This handler is called when a key is released.
+
+ The key event is available in via the KeyEvent \a event.
+
+ \qml
+ Item {
+ onKeyRelease: { if (event.key == Qt.Key_Enter) state='Enter' }
+ }
+ \endqml
+*/
+
+/*!
+ \fn void QFxItem::visibleChanged()
+
+ This signal is emitted when the visibility of the item changes.
+
+ \sa setVisible()
+*/
+
+/*!
+ \fn void QFxItem::opacityChanged()
+
+ This signal is emitted when the opacity of the item changes.
+
+ \sa opacity(), setOpacity()
+*/
+
+/*!
+ \fn void QFxItem::parentChanged()
+
+ This signal is emitted when the parent of the item changes.
+
+ \sa setItemParent()
+*/
+
+/*!
+ \fn void QFxItem::focusChanged()
+
+ This signal is emitted when the item's focus state changes.
+
+ \sa QSimpleCanvasItem::setFocus()
+*/
+
+/*!
+ \fn QFxItem::QFxItem(QFxItem *parent)
+
+ Constructs a QFxItem with the given \a parent.
+*/
+QFxItem::QFxItem(QFxItem* parent)
+ : QSimpleCanvasItem(*(new QFxItemPrivate), parent)
+{
+ Q_D(QFxItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+QFxItem::QFxItem(QFxItemPrivate &dd, QFxItem *parent)
+ : QSimpleCanvasItem(dd, parent)
+{
+ Q_D(QFxItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+void QFxItem::doUpdate()
+{
+ update();
+}
+
+/*!
+ Destroys the QFxItem.
+*/
+QFxItem::~QFxItem()
+{
+ Q_D(QFxItem);
+ for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
+ QFxAnchors *anchor = d->dependantAnchors.at(ii);
+ anchor->d_func()->clearItem(this);
+ }
+ for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
+ QFxAnchors *anchor = d->dependantAnchors.at(ii);
+ anchor->d_func()->updateOnComplete();
+ }
+ delete d->_anchorLines; d->_anchorLines = 0;
+}
+
+/*!
+ \qmlproperty enum Item::transformOrigin
+ This property holds the origin point around which scale and rotation transform.
+
+ Nine transform origins are available, as shown in the image below.
+
+ \image declarative-transformorigin.png
+
+ This example scales an image about its center.
+ \qml
+ Image {
+ source: "myimage.png"
+ transformOrigin: "Center"
+ scale: 4
+ }
+ \endqml
+
+ The default transform origin is \c TopLeft.
+*/
+
+/*!
+ \qmlproperty Item Item::parent
+ This property holds the parent of the item.
+*/
+
+/*!
+ \property QFxItem::parent
+ This property holds the parent of the item.
+*/
+void QFxItem::setItemParent(QFxItem *parent)
+{
+ setParent(parent);
+}
+
+/*!
+ \internal
+ \property QFxItem::moveToParent
+ Playing around with view2view transitions.
+ */
+
+/*!
+ \internal
+ */
+void QFxItem::moveToParent(QFxItem *parent)
+{
+ if (parent && itemParent()) {
+ QPointF me = itemParent()->mapToScene(QPointF(0,0));
+ QPointF them = parent->mapToScene(QPointF(0,0));
+
+ QPointF themx = parent->mapToScene(QPointF(1,0));
+ QPointF themy = parent->mapToScene(QPointF(0,1));
+
+ themx -= them;
+ themy -= them;
+
+ setItemParent(parent);
+
+ // XXX - this is silly and will only work in a few cases
+
+ /*
+ xDiff = rx * themx_x + ry * themy_x
+ yDiff = rx * themx_y + ry * themy_y
+ */
+
+ qreal rx = 0;
+ qreal ry = 0;
+ qreal xDiff = them.x() - me.x();
+ qreal yDiff = them.y() - me.y();
+
+
+ if (themx.x() == 0.) {
+ ry = xDiff / themy.x();
+ rx = (yDiff - ry * themy.y()) / themx.y();
+ } else if (themy.x() == 0.) {
+ rx = xDiff / themx.x();
+ ry = (yDiff - rx * themx.y()) / themy.y();
+ } else if (themx.y() == 0.) {
+ ry = yDiff / themy.y();
+ rx = (xDiff - ry * themy.x()) / themx.x();
+ } else if (themy.y() == 0.) {
+ rx = yDiff / themx.y();
+ ry = (xDiff - rx * themx.x()) / themy.x();
+ } else {
+ qreal div = (themy.x() * themx.y() - themy.y() * themx.x());
+
+ if (div != 0.)
+ rx = (themx.y() * xDiff - themx.x() * yDiff) / div;
+
+ if (themy.y() != 0.) ry = (yDiff - rx * themx.y()) / themy.y();
+ }
+
+ setX(x() - rx);
+ setY(y() - ry);
+ } else {
+ setItemParent(parent);
+ }
+}
+
+/*!
+ Returns the QFxItem parent of this item.
+*/
+QFxItem *QFxItem::itemParent() const
+{
+ return qobject_cast<QFxItem *>(QObject::parent());
+}
+
+/*!
+ \qmlproperty list<Item> Item::children
+ \qmlproperty list<Object> Item::resources
+
+ The children property contains the list of visual children of this item.
+ The resources property contains non-visual resources that you want to
+ reference by name.
+
+ Generally you can rely on Item's default property to handle all this for
+ you, but it can come in handy in some cases.
+
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rect {}
+ ]
+ resources: [
+ Component {
+ id: myComponent
+ Text {}
+ }
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \property QFxItem::children
+
+ This property contains the list of visual children of this item.
+*/
+
+/*!
+ \property QFxItem::resources
+
+ This property contains non-visual resources that you want to
+ reference by name.
+*/
+
+/*!
+ Returns true if all of the attributes set via QML have been set;
+ otherwise returns false.
+
+ \sa classComplete()
+*/
+bool QFxItem::isClassComplete() const
+{
+ Q_D(const QFxItem);
+ return d->_classComplete;
+}
+
+/*!
+ Returns true if construction of the QML component is complete; otherwise
+ returns false.
+
+ It is often desireable to delay some processing until the component is
+ completed.
+
+ \sa componentComplete()
+*/
+bool QFxItem::isComponentComplete() const
+{
+ Q_D(const QFxItem);
+ return d->_componentComplete;
+}
+
+/*!
+ \property QFxItem::anchors
+ \brief The anchors (alignments) used by the item.
+*/
+QFxAnchors *QFxItem::anchors()
+{
+ Q_D(QFxItem);
+ return d->anchors();
+}
+
+void QFxItemPrivate::data_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::data_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::data_append(QObject *o)
+{
+ Q_Q(QFxItem);
+ QFxItem *i = qobject_cast<QFxItem *>(o);
+ if (i)
+ q->children()->append(i);
+ else
+ resources_append(o);
+}
+
+void QFxItemPrivate::data_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxItemPrivate::data_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::data_clear()
+{
+ // ###
+}
+
+void QFxItemPrivate::resources_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::resources_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::resources_append(QObject *o)
+{
+ Q_Q(QFxItem);
+ o->setParent(q);
+}
+
+void QFxItemPrivate::resources_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxItemPrivate::resources_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::resources_clear()
+{
+ // ###
+}
+
+void QFxItemPrivate::children_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::children_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::children_append(QFxItem *i)
+{
+ Q_Q(QFxItem);
+ i->setParent(q);
+}
+
+void QFxItemPrivate::children_insert(int, QFxItem *)
+{
+ // ###
+}
+
+QFxItem *QFxItemPrivate::children_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::children_clear()
+{
+ // ###
+}
+
+/*!
+ \qmlproperty list<Object> Item::data
+ \default
+
+ The data property is allows you to freely mix visual children and resources
+ of an item. If you assign a visual item to the data list it becomes
+ a child and if you assign any other object type, it is added as a resource.
+
+ So you can write:
+ \qml
+ Item {
+ Text {}
+ Rect {}
+ Script {}
+ }
+ \endqml
+
+ instead of:
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rect {}
+ ]
+ resources: [
+ Script {}
+ ]
+ }
+ \endqml
+
+ data is a behind-the-scenes property: you should never need to explicitly
+ specify it.
+ */
+
+/*!
+ \property QFxItem::data
+
+ The data property is allows you to freely mix the visual children
+ and the non-visual resources of an item. If you assign a visual
+ item to the data list it becomes a child and if you assign any
+ other object type, it is added as a resource.
+
+ data is a behind-the-scenes property: you should never need to
+ explicitly specify it.
+ */
+QmlList<QObject *> *QFxItem::data()
+{
+ Q_D(QFxItem);
+ return &d->data;
+}
+
+/*!
+ \property QFxItem::contents
+ \brief An object that knows about the size of an item's children.
+
+ contents provides an easy way to access the (collective) width and
+ height of the item's children.
+*/
+QFxContents *QFxItem::contents()
+{
+ Q_D(QFxItem);
+ if (!d->_contents) {
+ d->_contents = new QFxContents;
+ d->_contents->setParent(this);
+ d->_contents->setItem(this);
+ }
+ return d->_contents;
+}
+
+/*!
+ \internal
+ \property QFxItem::qmlItem
+*/
+
+/*! \fn QFxItem *QFxItem::qmlItem() const
+ \internal
+ */
+QFxItem *QFxItem::qmlItem() const
+{
+ Q_D(const QFxItem);
+ return d->qmlItem;
+}
+
+/*!
+ \qmlproperty string Item::qml
+ This property holds the dynamic QML for the item.
+
+ This property is used for dynamically loading QML into the
+ item. Querying for the QML only has meaning if the QML has been
+ dynamically set; otherwise an empty string is returned.
+*/
+
+/*! \fn void QFxItem::qmlChanged()
+ This signal is emitted whenever the item's dynamic QML
+ string changes.
+
+ \sa setQml()
+ */
+
+/*!
+ \property QFxItem::qml
+ This property holds the dynamic QML for the item.
+
+ This property is used for dynamically loading QML into the
+ item. Querying for the QML only has meaning if the QML has been
+ dynamically set; otherwise an empty string is returned.
+*/
+QString QFxItem::qml() const
+{
+ Q_D(const QFxItem);
+ return d->_qml;
+}
+
+void QFxItem::setQml(const QString &qml)
+{
+ Q_D(QFxItem);
+ if (d->_qml == qml)
+ return;
+
+ if (!d->_qml.isEmpty()) {
+ QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml);
+ if (iter != d->_qmlChildren.end())
+ (*iter)->setOpacity(0.);
+ }
+
+ d->_qml = qml;
+ d->_qmlurl = qmlContext(this)->resolvedUri(qml);
+ d->qmlItem = 0;
+
+ if (d->_qml.isEmpty()) {
+ emit qmlChanged();
+ return;
+ }
+
+ QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml);
+ if (iter != d->_qmlChildren.end()) {
+ (*iter)->setOpacity(1.);
+ d->qmlItem = (*iter);
+ emit qmlChanged();
+ } else {
+ d->_qmlcomp =
+ new QmlComponent(qmlEngine(this), d->_qmlurl, this);
+ if (!d->_qmlcomp->isLoading())
+ qmlLoaded();
+ else
+ QObject::connect(d->_qmlcomp, SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(qmlLoaded()));
+ }
+}
+
+/*! \fn void QFxItem::newChildCreated(const QString &url, QScriptValue v)
+ This signal is emitted with the \a url and the script value \a v,
+ when a new child is created.
+ */
+
+/*!
+ \internal
+ */
+void QFxItem::qmlLoaded()
+{
+ Q_D(QFxItem);
+
+ { // newChild...
+ // ###
+ for (int i=0; i<d->_qmlnewloading.length(); ++i) {
+ QmlComponent *c = d->_qmlnewcomp.at(i);
+ if (c->isLoading())
+ continue;
+
+ QmlContext *ctxt = new QmlContext(qmlContext(this));
+ QObject* o = c ? c->create(ctxt):0;
+ QFxItem* ret = qobject_cast<QFxItem*>(o);
+ if (ret) {
+ ret->setItemParent(this);
+ QScriptValue v = qmlEngine(this)->scriptEngine()->newQObject(ret);
+ emit newChildCreated(d->_qmlnewloading.at(i).toString(),v);
+ }
+
+ delete c;
+ d->_qmlnewloading.removeAt(i);
+ d->_qmlnewcomp.removeAt(i);
+ --i;
+ }
+ }
+
+ // setQml...
+ if (d->_qmlcomp) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this));
+ ctxt->addDefaultObject(this);
+
+ QObject *obj = d->_qmlcomp->create(ctxt);
+ QFxItem *qmlChild = qobject_cast<QFxItem *>(obj);
+ if (qmlChild) {
+ qmlChild->setItemParent(this);
+ d->_qmlChildren.insert(d->_qml, qmlChild);
+ d->qmlItem = qmlChild;
+ } else {
+ delete qmlChild;
+ d->_qml = QString();
+ }
+ delete d->_qmlcomp;
+ d->_qmlcomp = 0;
+ emit qmlChanged();
+ }
+}
+
+/*!
+ \qmlproperty real Item::x
+ \qmlproperty real Item::y
+ \qmlproperty int Item::width
+ \qmlproperty int Item::height
+
+ Defines the item's position and size relative to its parent.
+
+ \qml
+ Item { x: 100; y: 100; width: 100; height: 100 }
+ \endqml
+ */
+
+/*!
+ \property QFxItem::width
+
+ Defines the item's width relative to its parent.
+ */
+
+/*!
+ \property QFxItem::height
+
+ Defines the item's height relative to its parent.
+ */
+
+/*!
+ \property QFxItem::x
+
+ The x coordinate of the item relative to its parent.
+*/
+
+/*!
+ \property QFxItem::y
+
+ The y coordinate of the item relative to its parent.
+*/
+
+/*!
+ \property QFxItem::z
+
+ The z coordinate of the item relative to its parent.
+
+ A negative z coordinate means the item will be painted below its parent.
+*/
+
+
+/*!
+ \qmlproperty real Item::z
+
+ Sets the stacking order of the item. By default the stacking order is 0.
+
+ Items with a higher stacking value are drawn on top of items with a
+ lower stacking order. Items with the same stacking value are drawn
+ bottom up in the order they appear. Items with a negative stacking
+ value are drawn under their parent's content.
+
+ The following example shows the various effects of stacking order.
+
+ \table
+ \row
+ \o \image declarative-item_stacking1.png
+ \o Same \c z - later children above earlier children:
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ }
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking2.png
+ \o Higher \c z on top:
+ \qml
+ Item {
+ Rect {
+ z: 1
+ color: "red"
+ width: 100; height: 100
+ }
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking3.png
+ \o Same \c z - children above parents:
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking4.png
+ \o Lower \c z below:
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ z: -1
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+ */
+
+/*!
+ This function is called to handle this item's changes in
+ geometry from \a oldGeometry to \a newGeometry. If the two
+ geometries are the same, it doesn't do anything.
+ */
+void QFxItem::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QFxItem);
+
+ if (d->_anchors)
+ d->_anchors->d_func()->updateMe();
+
+ if (newGeometry.size() != oldGeometry.size()) {
+ if (rotation() && transformOrigin() != QFxItem::TopLeft)
+ setRotation(rotation());
+ if (scale() && transformOrigin() != QFxItem::TopLeft)
+ setScale(scale());
+ }
+
+ if (newGeometry.x() != oldGeometry.x())
+ emit leftChanged();
+ if (newGeometry.width() != oldGeometry.width())
+ emit widthChanged();
+ if (newGeometry.y() != oldGeometry.y())
+ emit topChanged();
+ if (newGeometry.height() != oldGeometry.height())
+ emit heightChanged();
+
+ for(int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
+ QFxAnchors *anchor = d->dependantAnchors.at(ii);
+ anchor->d_func()->update(this, newGeometry, oldGeometry);
+ }
+}
+
+/*!
+ \qmlproperty bool Item::flipVertically
+ \qmlproperty bool Item::flipHorizontally
+
+ When set, the item will be displayed flipped horizontally or vertically
+ about its center.
+ */
+
+/*!
+ \property QFxItem::flipVertically
+
+ When set, the item will be displayed flipped horizontally or vertically
+ about its center.
+ */
+bool QFxItem::flipVertically() const
+{
+ return flip() & VerticalFlip;
+}
+
+void QFxItem::setFlipVertically(bool v)
+{
+ if (v)
+ setFlip((QSimpleCanvasItem::Flip)(flip() | VerticalFlip));
+ else
+ setFlip((QSimpleCanvasItem::Flip)(flip() & ~VerticalFlip));
+}
+
+/*!
+ \property QFxItem::flipHorizontally
+
+ When set, the item will be displayed flipped horizontally or vertically
+ about its center.
+ */
+bool QFxItem::flipHorizontally() const
+{
+ return flip() & HorizontalFlip;
+}
+
+void QFxItem::setFlipHorizontally(bool v)
+{
+ if (v)
+ setFlip((QSimpleCanvasItem::Flip)(flip() | HorizontalFlip));
+ else
+ setFlip((QSimpleCanvasItem::Flip)(flip() & ~HorizontalFlip));
+}
+
+/*! \fn void QFxItem::keyPress(QFxKeyEvent *event)
+ This signal is emitted by keyPressEvent() for the \a event.
+ */
+
+/*! \fn void QFxItem::keyRelease(QFxKeyEvent *event)
+ This signal is emitted by keyReleaseEvent() for the \a event.
+ */
+
+/*!
+ \reimp
+*/
+void QFxItem::keyPressEvent(QKeyEvent *event)
+{
+ QFxKeyEvent ke(*event);
+ emit keyPress(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (itemParent() && !ke.isAccepted())
+ itemParent()->keyPressEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QFxItem::keyReleaseEvent(QKeyEvent *event)
+{
+ QFxKeyEvent ke(*event);
+ emit keyRelease(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (itemParent() && !ke.isAccepted())
+ itemParent()->keyReleaseEvent(event);
+}
+
+/*!
+ Returns the bounding rectangle of the item in scene coordinates.
+*/
+QRectF QFxItem::sceneBoundingRect() const
+{
+ return QRectF(mapToScene(QPointF(0,0)), QSize(width(), height()));
+}
+
+/*!
+ \qmlproperty string Item::id
+ This property holds the identifier for the item.
+
+ The identifier can be used in bindings and other expressions to
+ refer to the item. For example:
+
+ \qml
+ Text { id: myText; ... }
+ Text { text: myText.text }
+ \endqml
+
+ The identifier is available throughout to the \l {components}{component}
+ where it is declared. The identifier must be unique in thecomponent.
+*/
+
+/*!
+ \property QFxItem::id
+ This property holds the identifier for the item.
+
+ The identifier can be used in bindings and other expressions to
+ refer to the item. For example:
+
+ \qml
+ Text { id: myText; ... }
+ Text { text: myText.text }
+ \endqml
+
+ The identifier is available throughout the \l {components}{component}
+ where it is declared. The identifier must be unique in thecomponent.
+*/
+QString QFxItem::id() const
+{
+ Q_D(const QFxItem);
+ return d->_id;
+}
+
+void QFxItem::setId(const QString &id)
+{
+ Q_D(QFxItem);
+ setObjectName(id);
+ d->_id = id;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::left() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->left;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::right() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->right;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::horizontalCenter() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->hCenter;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::top() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->top;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::bottom() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->bottom;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::verticalCenter() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->vCenter;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::baseline() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->baseline;
+}
+
+/*!
+ \property QFxItem::top
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::bottom
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::left
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::right
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::horizontalCenter
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::verticalCenter
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \qmlproperty AnchorLine Item::top
+ \qmlproperty AnchorLine Item::bottom
+ \qmlproperty AnchorLine Item::left
+ \qmlproperty AnchorLine Item::right
+ \qmlproperty AnchorLine Item::horizontalCenter
+ \qmlproperty AnchorLine Item::verticalCenter
+ \qmlproperty AnchorLine Item::baseline
+
+ The anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \qmlproperty AnchorLine Item::anchors.top
+ \qmlproperty AnchorLine Item::anchors.bottom
+ \qmlproperty AnchorLine Item::anchors.left
+ \qmlproperty AnchorLine Item::anchors.right
+ \qmlproperty AnchorLine Item::anchors.horizontalCenter
+ \qmlproperty AnchorLine Item::anchors.verticalCenter
+ \qmlproperty AnchorLine Item::anchors.baseline
+
+ \qmlproperty Item Item::anchors.fill
+
+ \qmlproperty int Item::anchors.topMargin
+ \qmlproperty int Item::anchors.bottomMargin
+ \qmlproperty int Item::anchors.leftMargin
+ \qmlproperty int Item::anchors.rightMargin
+ \qmlproperty int Item::anchors.horizontalCenterOffset
+ \qmlproperty int Item::anchors.verticalCenterOffset
+
+ Anchors provide a way to position an item by specifying its
+ relationship with other items.
+
+ Margins apply to top, bottom, left, right, and fill anchors.
+
+ Offsets apply for horizontal and vertical center anchors.
+
+ \table
+ \row
+ \o \image declarative-anchors_example.png
+ \o Text anchored to Image, horizontally centered and vertically below, with a margin.
+ \qml
+ Image { id: pic; ... }
+ Text {
+ id: label
+ anchors.horizontalCenter: pic.horizontalCenter
+ anchors.top: pic.bottom
+ anchors.topMargin: 5
+ ...
+ }
+ \endqml
+ \row
+ \o \image declarative-anchors_example2.png
+ \o
+ Left of Text anchored to right of Image, with a margin. The y
+ property of both defaults to 0.
+
+ \qml
+ Image { id: pic; ... }
+ Text {
+ id: label
+ anchors.left: pic.right
+ anchors.leftMargin: 5
+ ...
+ }
+ \endqml
+ \endtable
+
+ anchors.fill provides a convenient way for one item to have the
+ same geometry as another item, and is equivalent to connecting all
+ four directional anchors.
+
+ \note You can only anchor an item to siblings or a parent.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::baselineOffset
+ \brief The position of the item's baseline in local coordinates.
+
+ The baseline of a Text item is the imaginary line on which the text
+ sits. Controls containing text usually set their baseline to the
+ baseline of their text.
+
+ For non-text items, a default baseline offset of 0 is used.
+*/
+int QFxItem::baselineOffset() const
+{
+ Q_D(const QFxItem);
+ if (!d->_baselineOffset.isValid()) {
+ return 0;
+ } else
+ return d->_baselineOffset;
+}
+
+/*!
+ \internal
+*/
+void QFxItem::setBaselineOffset(int offset)
+{
+ Q_D(QFxItem);
+ if (offset == d->_baselineOffset)
+ return;
+
+ d->_baselineOffset = offset;
+ emit baselineOffsetChanged();
+
+ for(int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
+ QFxAnchors *anchor = d->dependantAnchors.at(ii);
+ anchor->d_func()->updateVerticalAnchors();
+ }
+}
+
+/*!
+ \qmlproperty real Item::rotation
+ This property holds the rotation of the item in degrees.
+
+ This specifies how many degrees to rotate the item around its origin (0,0).
+ The default rotation is 0 degrees (i.e. not rotated at all).
+
+ \table
+ \row
+ \o \image declarative-rotation.png
+ \o
+ \qml
+ Rect {
+ color: "blue"
+ width: 100; height: 100
+ Rect {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rect {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ rotation: 30
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*! \fn void QFxItem::rotationChanged()
+ This signal is emitted when the rotation property is changed.
+
+ \sa setRotation()
+ */
+
+/*!
+ \property QFxItem::rotation
+ This property holds the rotation of the item in degrees.
+
+ This specifies how many degrees to rotate the item around its origin (0,0).
+ The default rotation is 0 degrees (i.e. not rotated at all).
+*/
+qreal QFxItem::rotation() const
+{
+ Q_D(const QFxItem);
+ return d->_rotation;
+}
+
+void QFxItem::setRotation(qreal rotation)
+{
+ Q_D(QFxItem);
+ if (d->_rotation == rotation)
+ return;
+ d->_rotation = rotation;
+#if defined(QFX_RENDER_OPENGL)
+ QMatrix4x4 trans;
+ QPointF to = transformOriginPoint();
+ trans.translate(to.x(), to.y());
+ trans.rotate(d->_rotation, 0, 0, 1);
+ trans.translate(-to.x(), -to.y());
+#else
+ QTransform trans;
+ QPointF to = transformOriginPoint();
+ trans.translate(to.x(), to.y());
+ trans.rotate(d->_rotation);
+ trans.translate(-to.x(), -to.y());
+#endif
+ setTransform(trans);
+ emit rotationChanged();
+}
+
+/*!
+ \qmlproperty real Item::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's origin (0,0).
+
+ \table
+ \row
+ \o \image declarative-scale.png
+ \o
+ \qml
+ Rect {
+ color: "blue"
+ width: 100; height: 100
+ Rect {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rect {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ scale: 1.4
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*!
+ \property QFxItem::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's origin (0,0).
+*/
+qreal QFxItem::scale() const
+{
+ return QSimpleCanvasItem::scale();
+}
+
+void QFxItem::setScale(qreal s)
+{
+ if (QSimpleCanvasItem::scale() == s) return;
+ QSimpleCanvasItem::setScale(s);
+ emit scaleChanged();
+ update();
+}
+
+/*!
+ \qmlproperty real Item::opacity
+
+ The opacity of the item. Opacity is specified as a number between 0
+ (fully transparent) and 1 (fully opaque). The default is 1.
+
+ Opacity is an \e inherited attribute. That is, the opacity is
+ also applied individually to child items. In almost all cases this
+ is what you want. If you can spot the issue in the following
+ example, you might need to use an opacity filter (not yet available) instead.
+
+ \table
+ \row
+ \o \image declarative-item_opacity1.png
+ \o
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_opacity2.png
+ \o
+ \qml
+ Item {
+ Rect {
+ opacity: 0.5
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*!
+ \property QFxItem::opacity
+
+ The opacity of the item. Opacity is specified as a number between 0
+ (fully transparent) and 1 (fully opaque). The default is 1.
+
+ Opacity is an \e inherited attribute. That is, the opacity is
+ also applied individually to child items.
+*/
+
+qreal QFxItem::opacity() const
+{
+ return QSimpleCanvasItem::visible();
+}
+
+void QFxItem::setOpacity(qreal v)
+{
+ if (v == QSimpleCanvasItem::visible())
+ return;
+
+ if (v < 0) v = 0;
+ else if (v > 1) v = 1;
+ QSimpleCanvasItem::setVisible(v);
+
+ emit opacityChanged();
+}
+
+/*!
+ Returns a value indicating whether the mouse should
+ remain with this item.
+ */
+bool QFxItem::keepMouseGrab() const
+{
+ Q_D(const QFxItem);
+ return d->_keepMouse;
+}
+
+/*!
+ The flag indicating whether the mouse should remain
+ with this item is set to \a keep.
+ */
+void QFxItem::setKeepMouseGrab(bool keep)
+{
+ Q_D(QFxItem);
+ d->_keepMouse = keep;
+}
+
+/*!
+ This function emits the \e activeFocusChanged signal.
+ \a flag is not used.
+ */
+void QFxItem::activeFocusChanged(bool flag)
+{
+ Q_UNUSED(flag);
+ emit activeFocusChanged();
+}
+
+/*!
+ This function emits the \e focusChanged signal.
+ \a flag is not used.
+ */
+void QFxItem::focusChanged(bool flag)
+{
+ Q_UNUSED(flag);
+ emit focusChanged();
+}
+
+QmlList<QFxItem *> *QFxItem::children()
+{
+ Q_D(QFxItem);
+ return &(d->children);
+}
+
+QmlList<QObject *> *QFxItem::resources()
+{
+ Q_D(QFxItem);
+ return &(d->resources);
+}
+
+/*!
+ \qmlproperty list<State> Item::states
+ This property holds a list of states defined by the item.
+
+ \qml
+ Item {
+ states: [
+ State { ... },
+ State { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \property QFxItem::states
+ This property holds a list of states defined by the item.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QmlList<QmlState *>* QFxItem::states()
+{
+ Q_D(QFxItem);
+ return d->states()->statesProperty();
+}
+
+/*!
+ \qmlproperty list<Transition> Item::transitions
+ This property holds a list of transitions defined by the item.
+
+ \qml
+ Item {
+ transitions: [
+ Transition { ... },
+ Transition { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \property QFxItem::transitions
+ This property holds a list of transitions defined by the item.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QmlList<QmlTransition *>* QFxItem::transitions()
+{
+ Q_D(QFxItem);
+ return d->states()->transitionsProperty();
+}
+
+/*!
+ \internal
+ \property QFxItem::filter
+*/
+
+/*!
+ \qmlproperty list<Filter> Item::filter
+ This property holds a list of graphical filters to be applied to the item.
+
+ \l {Filter}{Filters} include things like \l {Blur}{blurring}
+ the item, or giving it a \l Reflection. Some
+ filters may not be available on all canvases; if a filter is not
+ available on a certain canvas, it will simply not be applied for
+ that canvas (but the QML will still be considered valid).
+
+ \qml
+ Item {
+ filter: [
+ Blur { ... },
+ Relection { ... }
+ ...
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool Item::clip
+ This property holds whether clipping is enabled.
+
+ if clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \property QFxItem::clip
+ This property holds whether clipping is enabled.
+
+ if clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ Returns the state with \a name. Returns 0 if no matching state is found.
+*/
+QmlState *QFxItem::findState(const QString &name) const
+{
+ Q_D(const QFxItem);
+ if (!d->_stateGroup)
+ return 0;
+ else
+ return d->_stateGroup->findState(name);
+}
+
+/*!
+ \qmlproperty string Item::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ Script {
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ }
+ \endqml
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \property QFxItem::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ Script {
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ }
+ \endqml
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QString QFxItem::state() const
+{
+ Q_D(const QFxItem);
+ if (!d->_stateGroup)
+ return QString();
+ else
+ return d->_stateGroup->state();
+}
+
+void QFxItem::setState(const QString &state)
+{
+ Q_D(QFxItem);
+ d->states()->setState(state);
+}
+
+/*!
+ \qmlproperty list<Transform> Item::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+
+/*!
+ \property QFxItem::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+QList<QFxTransform *> *QFxItem::transform()
+{
+ Q_D(QFxItem);
+ return &(d->_transform);
+}
+
+/*!
+ \property QFxItem::focus
+ This property holds the item's focus state.
+*/
+
+/*!
+ \property QFxItem::focusable
+ This property holds whether the item has focus state.
+*/
+
+/*!
+ Returns true if the item is visible; otherwise returns false.
+
+ An item is considered visible if its opacity is not 0.
+*/
+bool QFxItem::isVisible() const
+{
+ Q_D(const QFxItem);
+ return d->visible;
+}
+
+/*!
+ \property QFxItem::visible
+
+ This property specifies whether the item is visible or invisible.
+
+ Setting visibility to false sets opacity to 0. Setting the
+ visibility to true restores the opacity to its previous value.
+
+ \sa isVisible()
+*/
+void QFxItem::setVisible(bool visible)
+{
+ Q_D(QFxItem);
+ if (visible == d->visible)
+ return;
+
+ d->visible = visible;
+ if (visible)
+ setOpacity(d->visibleOp);
+ else {
+ d->visibleOp = opacity();
+ setOpacity(0);
+ }
+
+ emit visibleChanged();
+}
+
+/*! \internal
+*/
+void QFxItem::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << metaObject()->className() << "(" << (void *)static_cast<QFxItem*>(this) << ", " << (void *)static_cast<QSimpleCanvasItem*>(this) << "):" << x() << y() << width() << height() << (void *) itemParent();
+}
+
+/*! \internal
+*/
+QString QFxItem::propertyInfo() const
+{
+ return QString();
+}
+
+/*!
+ Creates a new child of the given component \a type. The
+ newChildCreated() signal will be emitted when and if the child is
+ successfully created.
+
+ \preliminary
+*/
+void QFxItem::newChild(const QString &type)
+{
+ Q_D(QFxItem);
+
+ QUrl url = qmlContext(this)->resolvedUri(type);
+ if (url.isEmpty())
+ return;
+
+ d->_qmlnewloading.append(url);
+ d->_qmlnewcomp.append(new QmlComponent(qmlEngine(this), url, this));
+
+ if (!d->_qmlnewcomp.last()->isLoading())
+ qmlLoaded();
+ else
+ connect(d->_qmlnewcomp.last(), SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(qmlLoaded()));
+}
+
+/*!
+ classBegin() is called when the item is constructed, but its
+ properties have not yet been set.
+
+ \sa classComplete(), componentComplete(), isClassComplete(), isComponentComplete()
+*/
+void QFxItem::classBegin()
+{
+ Q_D(QFxItem);
+ d->_classComplete = false;
+ d->_componentComplete = false;
+ if (d->_stateGroup)
+ d->_stateGroup->classBegin();
+}
+
+/*!
+ classComplete() is called when all properties specified in QML
+ have been assigned. It is sometimes desireable to delay some
+ processing until all property assignments are complete.
+*/
+void QFxItem::classComplete()
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ItemComponentComplete> cc;
+#endif
+ Q_D(QFxItem);
+ d->_classComplete = true;
+ if (d->_stateGroup)
+ d->_stateGroup->classComplete();
+}
+
+/*!
+ componentComplete() is called when all items in the component
+ have been constructed. It is often desireable to delay some
+ processing until the component is complete an all bindings in the
+ component have been resolved.
+*/
+void QFxItem::componentComplete()
+{
+ Q_D(QFxItem);
+ d->_componentComplete = true;
+ if (d->_stateGroup)
+ d->_stateGroup->componentComplete();
+ if (d->_anchors)
+ d->anchors()->d_func()->updateOnComplete();
+ if (!d->_transform.isEmpty())
+ updateTransform();
+}
+
+/*! \internal
+*/
+void QFxItem::parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *)
+{
+ emit parentChanged();
+}
+
+/*! \internal
+*/
+void QFxItem::reparentItems()
+{
+ qFatal("EEK");
+}
+
+/*!
+ \internal
+*/
+void QFxItem::updateTransform()
+{
+ Q_D(QFxItem);
+ QSimpleCanvas::Matrix trans;
+ for (int ii = d->_transform.count() - 1; ii >= 0; --ii) {
+ QFxTransform *a = d->_transform.at(ii);
+ if (!a->isIdentity())
+ trans = a->transform() * trans;
+ }
+
+ setTransform(trans);
+ transformChanged(trans);
+}
+
+/*!
+ \internal
+*/
+void QFxItem::transformChanged(const QSimpleCanvas::Matrix &)
+{
+}
+
+QmlStateGroup *QFxItemPrivate::states()
+{
+ Q_Q(QFxItem);
+ if (!_stateGroup) {
+ _stateGroup = new QmlStateGroup(q);
+ if (!_classComplete)
+ _stateGroup->classBegin();
+ QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)),
+ q, SIGNAL(stateChanged(QString)));
+ }
+
+ return _stateGroup;
+}
+
+QFxItemPrivate::AnchorLines::AnchorLines(QFxItem *q)
+{
+ left.item = q;
+ left.anchorLine = QFxAnchorLine::Left;
+ right.item = q;
+ right.anchorLine = QFxAnchorLine::Right;
+ hCenter.item = q;
+ hCenter.anchorLine = QFxAnchorLine::HCenter;
+ top.item = q;
+ top.anchorLine = QFxAnchorLine::Top;
+ bottom.item = q;
+ bottom.anchorLine = QFxAnchorLine::Bottom;
+ vCenter.item = q;
+ vCenter.anchorLine = QFxAnchorLine::VCenter;
+ baseline.item = q;
+ baseline.anchorLine = QFxAnchorLine::Baseline;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h
new file mode 100644
index 0000000..8ca1f9e
--- /dev/null
+++ b/src/declarative/fx/qfxitem.h
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXITEM_H
+#define QFXITEM_H
+
+#include <QtCore/QObject>
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/QList>
+#include <QtDeclarative/qfxanchors.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qfxscalegrid.h>
+#include <QtDeclarative/qsimplecanvasitem.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlstate.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QFxContents : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int height READ height NOTIFY heightChanged)
+ Q_PROPERTY(int width READ width NOTIFY widthChanged)
+public:
+ QFxContents();
+
+ int height() const;
+
+ int width() const;
+
+ void setItem(QFxItem *item);
+
+public Q_SLOTS:
+ void calcHeight();
+ void calcWidth();
+
+Q_SIGNALS:
+ void heightChanged();
+ void widthChanged();
+
+private:
+ QFxItem *_item;
+ int _height;
+ int _width;
+};
+QML_DECLARE_TYPE(QFxContents)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFxAnchors::UsedAnchors)
+
+class QmlState;
+class QmlTransition;
+class QFxTransform;
+class QFxKeyEvent;
+class QFxItemPrivate;
+class Q_DECLARATIVE_EXPORT QFxItem : public QSimpleCanvasItem, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QFxItem * parent READ itemParent WRITE setItemParent NOTIFY parentChanged DESIGNABLE false)
+ Q_PROPERTY(QFxItem * moveToParent READ itemParent WRITE moveToParent NOTIFY parentChanged DESIGNABLE false)
+ Q_PROPERTY(QString id READ id WRITE setId)
+ Q_PROPERTY(QmlList<QFxItem *>* children READ children DESIGNABLE false)
+ Q_PROPERTY(QmlList<QObject *>* resources READ resources DESIGNABLE false)
+ Q_PROPERTY(QFxAnchors * anchors READ anchors DESIGNABLE false)
+ Q_PROPERTY(QmlList<QObject *> *data READ data DESIGNABLE false)
+ Q_PROPERTY(QFxContents * contents READ contents DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlState *>* states READ states DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitions DESIGNABLE false)
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QString qml READ qml WRITE setQml NOTIFY qmlChanged)
+ Q_PROPERTY(QFxItem *qmlItem READ qmlItem NOTIFY qmlChanged)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY leftChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY topChanged)
+ Q_PROPERTY(qreal z READ z WRITE setZ)
+ Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
+ Q_PROPERTY(bool flipVertically READ flipVertically WRITE setFlipVertically)
+ Q_PROPERTY(bool flipHorizontally READ flipHorizontally WRITE setFlipHorizontally)
+ Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
+ Q_PROPERTY(int baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
+ Q_PROPERTY(QFxAnchorLine left READ left)
+ Q_PROPERTY(QFxAnchorLine right READ right)
+ Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter)
+ Q_PROPERTY(QFxAnchorLine top READ top)
+ Q_PROPERTY(QFxAnchorLine bottom READ bottom)
+ Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter)
+ Q_PROPERTY(QFxAnchorLine baseline READ baseline)
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
+ Q_PROPERTY(QSimpleCanvasFilter *filter READ filter WRITE setFilter)
+ Q_PROPERTY(bool clip READ clip WRITE setClip)
+ Q_PROPERTY(bool focusable READ isFocusable WRITE setFocusable)
+ Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged)
+ Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged)
+ Q_PROPERTY(QList<QFxTransform *>* transform READ transform)
+ Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+ typedef QHash<QString, QFxItem *> QmlChildren;
+
+public:
+ QFxItem(QFxItem *parent = 0);
+ virtual ~QFxItem();
+
+ QFxItem *itemParent() const;
+ void setItemParent(QFxItem *parent);
+
+ void moveToParent(QFxItem *parent);
+
+ QString id() const;
+ void setId(const QString &);
+
+ QmlList<QObject *> *data();
+ QmlList<QFxItem *> *children();
+ QmlList<QObject *> *resources();
+
+ QFxAnchors *anchors();
+
+ QFxContents *contents();
+
+ QmlList<QmlState *>* states();
+ QmlState *findState(const QString &name) const;
+
+ QmlList<QmlTransition *>* transitions();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QFxItem *qmlItem() const;
+ QString qml() const;
+ void setQml(const QString &);
+
+ bool flipVertically() const;
+ void setFlipVertically(bool);
+ bool flipHorizontally() const;
+ void setFlipHorizontally(bool);
+
+ int baselineOffset() const;
+ void setBaselineOffset(int);
+
+ qreal rotation() const;
+ void setRotation(qreal);
+
+ qreal scale() const;
+ void setScale(qreal);
+
+ qreal opacity() const;
+ virtual void setOpacity(qreal);
+
+ QList<QFxTransform *> *transform();
+
+ bool isVisible() const;
+ void setVisible(bool);
+
+ virtual void dump(int depth = 0);
+ virtual QString propertyInfo() const;
+
+ bool isClassComplete() const;
+ bool isComponentComplete() const;
+
+ QRectF sceneBoundingRect() const;
+
+ void updateTransform();
+
+ bool keepMouseGrab() const;
+ void setKeepMouseGrab(bool);
+
+public Q_SLOTS:
+ void newChild(const QString &url);
+
+Q_SIGNALS:
+ void leftChanged();
+ void widthChanged();
+ void heightChanged();
+ void topChanged();
+ void baselineOffsetChanged();
+ void stateChanged(const QString &);
+ void focusChanged();
+ void activeFocusChanged();
+ void parentChanged();
+ void keyPress(QFxKeyEvent *event);
+ void keyRelease(QFxKeyEvent *event);
+ void rotationChanged();
+ void scaleChanged();
+ void opacityChanged();
+ void visibleChanged();
+ void qmlChanged();
+ void newChildCreated(const QString &url, QScriptValue);
+
+protected:
+ virtual void transformChanged(const QSimpleCanvas::Matrix &);
+ virtual void classBegin();
+ virtual void classComplete();
+ virtual void componentComplete();
+ virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *);
+ virtual void reparentItems();
+ virtual void focusChanged(bool);
+ virtual void activeFocusChanged(bool);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private Q_SLOTS:
+ void doUpdate();
+ void qmlLoaded();
+
+protected:
+ QFxItem(QFxItemPrivate &dd, QFxItem *parent = 0);
+
+private:
+ QFxAnchorLine left() const;
+ QFxAnchorLine right() const;
+ QFxAnchorLine horizontalCenter() const;
+ QFxAnchorLine top() const;
+ QFxAnchorLine bottom() const;
+ QFxAnchorLine verticalCenter() const;
+ QFxAnchorLine baseline() const;
+
+ void init(QFxItem *parent);
+ friend class QmlStatePrivate;
+ friend class QFxAnchors;
+ Q_DISABLE_COPY(QFxItem)
+ Q_DECLARE_PRIVATE(QFxItem)
+};
+QML_DECLARE_TYPE(QFxItem)
+
+QML_DECLARE_TYPE(QSimpleCanvasFilter)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXITEM_H
diff --git a/src/declarative/fx/qfxitem_p.h b/src/declarative/fx/qfxitem_p.h
new file mode 100644
index 0000000..a54f523
--- /dev/null
+++ b/src/declarative/fx/qfxitem_p.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXITEM_P_H
+#define QFXITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDeclarative/qfxitem.h>
+#include <private/qsimplecanvasitem_p.h>
+#include <private/qmlnullablevalue_p.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+
+class QFxItemPrivate : public QSimpleCanvasItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxItem)
+
+ typedef QHash<QString, QFxItem *> QmlChildren;
+
+public:
+ QFxItemPrivate()
+ : _anchors(0), _contents(0), qmlItem(0), _qmlcomp(0),
+ _baselineOffset(0), _rotation(0.),
+ _classComplete(true), _componentComplete(true), _keepMouse(false),
+ visible(true), _anchorLines(0), visibleOp(1), reparentedChildren(0),
+ _stateGroup(0)
+ {}
+ ~QFxItemPrivate()
+ { delete _anchors; }
+
+ void init(QFxItem *parent)
+ {
+ Q_Q(QFxItem);
+
+ if (parent)
+ q->setItemParent(parent);
+ _baselineOffset.invalidate();
+ q->setAcceptedMouseButtons(Qt::NoButton);
+ }
+
+ QString _id;
+
+ // data property
+ void data_removeAt(int);
+ int data_count() const;
+ void data_append(QObject *);
+ void data_insert(int, QObject *);
+ QObject *data_at(int) const;
+ void data_clear();
+ QML_DECLARE_LIST_PROXY(QFxItemPrivate, QObject *, data)
+
+ // resources property
+ void resources_removeAt(int);
+ int resources_count() const;
+ void resources_append(QObject *);
+ void resources_insert(int, QObject *);
+ QObject *resources_at(int) const;
+ void resources_clear();
+ QML_DECLARE_LIST_PROXY(QFxItemPrivate, QObject *, resources)
+
+ // children property
+ void children_removeAt(int);
+ int children_count() const;
+ void children_append(QFxItem *);
+ void children_insert(int, QFxItem *);
+ QFxItem *children_at(int) const;
+ void children_clear();
+ QML_DECLARE_LIST_PROXY(QFxItemPrivate, QFxItem *, children)
+
+ QList<QFxTransform *> _transform;
+ QFxAnchors *anchors() {
+ if (!_anchors) {
+ Q_Q(QFxItem);
+ _anchors = new QFxAnchors;
+ _anchors->setItem(q);
+ }
+ return _anchors;
+ }
+ QList<QFxAnchors *> dependantAnchors;
+ QFxAnchors *_anchors;
+ QFxContents *_contents;
+ QFxItem *qmlItem;
+ QUrl _qmlurl;
+ QmlComponent *_qmlcomp;
+ QString _qml;
+ QList<QUrl> _qmlnewloading;
+ QList<QmlComponent*> _qmlnewcomp;
+
+ QmlNullableValue<int> _baselineOffset;
+ float _rotation;
+
+ bool _classComplete:1;
+ bool _componentComplete:1;
+ bool _keepMouse:1;
+ bool visible:1;
+
+ QmlChildren _qmlChildren;
+
+ struct AnchorLines {
+ AnchorLines(QFxItem *);
+ QFxAnchorLine left;
+ QFxAnchorLine right;
+ QFxAnchorLine hCenter;
+ QFxAnchorLine top;
+ QFxAnchorLine bottom;
+ QFxAnchorLine vCenter;
+ QFxAnchorLine baseline;
+ };
+ mutable AnchorLines *_anchorLines;
+ AnchorLines *anchorLines() const {
+ Q_Q(const QFxItem);
+ if (!_anchorLines) _anchorLines =
+ new AnchorLines(const_cast<QFxItem *>(q));
+ return _anchorLines;
+ }
+
+ float visibleOp;
+
+ int reparentedChildren;
+
+ QmlStateGroup *states();
+ QmlStateGroup *_stateGroup;
+};
+
+QT_END_NAMESPACE
+#endif // QFXITEM_P_H
diff --git a/src/declarative/fx/qfxkeyactions.cpp b/src/declarative/fx/qfxkeyactions.cpp
new file mode 100644
index 0000000..4aae74f
--- /dev/null
+++ b/src/declarative/fx/qfxkeyactions.cpp
@@ -0,0 +1,920 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxkeyactions.h"
+#include <qmlexpression.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxKeyActions,KeyActions)
+
+class QFxKeyActionsPrivate
+{
+public:
+ QFxKeyActionsPrivate();
+
+ bool enabled;
+
+ uint keys1;
+ uint keys2;
+
+ QHash<Qt::Key, QString> actions;
+
+ bool key(Qt::Key) const;
+ QString action(Qt::Key) const;
+ void setKey(Qt::Key, bool = true);
+
+ bool testBit(int) const;
+ void setBit(int, bool);
+
+ int keyToBit(Qt::Key) const;
+
+ QString keyExpr(Qt::Key) const;
+ void setKeyExpr(Qt::Key, const QString &);
+};
+
+QFxKeyActionsPrivate::QFxKeyActionsPrivate()
+: enabled(true), keys1(0), keys2(0)
+{
+}
+
+int QFxKeyActionsPrivate::keyToBit(Qt::Key k) const
+{
+ if (k >= Qt::Key_A && k <= Qt::Key_Z ) {
+ return k - Qt::Key_A;
+ } else if (k >= Qt::Key_Left && k <= Qt::Key_Down) {
+ return 26 + k - Qt::Key_Left;
+ } else if (k >= Qt::Key_0 && k <= Qt::Key_9) {
+ return 30 + k - Qt::Key_0;
+ } else if (k >= Qt::Key_Context1 && k <= Qt::Key_Flip) {
+ return 40 + k - Qt::Key_Context1;
+ } else if (k >= Qt::Key_Select && k <= Qt::Key_No) {
+ return 47 + k - Qt::Key_Select;
+ } else {
+ const int start = 50;
+ switch(k) {
+ case Qt::Key_Escape:
+ return start + 0;
+ case Qt::Key_Return:
+ return start + 1;
+ case Qt::Key_Enter:
+ return start + 2;
+ case Qt::Key_Delete:
+ return start + 3;
+ case Qt::Key_Space:
+ return start + 4;
+ case Qt::Key_Back:
+ return start + 5;
+ case Qt::Key_unknown:
+ return start + 6;
+ case Qt::Key_Asterisk:
+ return start + 7;
+ default:
+ return -1;
+ }
+ }
+}
+
+bool QFxKeyActionsPrivate::key(Qt::Key k) const
+{
+ int b = keyToBit(k);
+ bool rv = testBit(b);
+ if (!rv && k != Qt::Key_Shift)
+ rv = testBit(keyToBit(Qt::Key_unknown));
+ return rv;
+}
+
+QString QFxKeyActionsPrivate::action(Qt::Key k) const
+{
+ int b = keyToBit(k);
+ if (b != -1 && testBit(b))
+ return actions.value(k);
+ else
+ return actions.value(Qt::Key_unknown);
+}
+
+void QFxKeyActionsPrivate::setKey(Qt::Key k, bool v)
+{
+ int b = keyToBit(k);
+ if (b == -1)
+ return;
+
+ setBit(b, v);
+}
+
+bool QFxKeyActionsPrivate::testBit(int b) const
+{
+ if (b < 0)
+ return false;
+
+ if (b < 32)
+ return keys1 & (1 << b);
+ else
+ return keys2 & (1 << (b - 32));
+}
+
+void QFxKeyActionsPrivate::setBit(int b, bool v)
+{
+ if (v) {
+ if (b < 32)
+ keys1 |= (1 << b);
+ else
+ keys2 |= (1 << (b - 32));
+ } else {
+ if (b < 32)
+ keys1 &= ~(1 << b);
+ else
+ keys2 &= ~(1 << (b - 32));
+ }
+}
+
+
+/*!
+ \qmlclass KeyActions
+ \brief The KeyActions item enables simple key handling.
+ \inherits Item
+
+ KeyActions is typically used in basic key handling scenarios where writing
+ JavaScript key handling routines would be unnecessarily complicated. The
+ KeyActions item has a collection of properties that correspond to a
+ selection of common keys. When a given key is pressed, the item executes
+ the action script assigned to the matching property. If no action has
+ been set the KeyActions item does nothing.
+
+ To receive (and susequently respond to) key presses, the KeyActions class
+ must be in the current focus chain, just like any other item.
+
+ For basic mouse handling, see \l MouseRegion.
+
+ KeyActions is an invisible item: it is never painted.
+*/
+QFxKeyActions::QFxKeyActions(QFxItem *parent)
+: QFxItem(parent), d(new QFxKeyActionsPrivate)
+{
+}
+
+QFxKeyActions::~QFxKeyActions()
+{
+ delete d;
+}
+
+QString QFxKeyActionsPrivate::keyExpr(Qt::Key k) const
+{
+ if (key(k))
+ return actions.value(k);
+ else
+ return QString();
+}
+
+void QFxKeyActionsPrivate::setKeyExpr(Qt::Key k, const QString &expr)
+{
+ if (expr.isEmpty()) {
+ if (key(k)) {
+ actions.remove(k);
+ setKey(k, false);
+ }
+ } else {
+ actions.insert(k, expr);
+ setKey(k);
+ }
+}
+
+/*!
+ \qmlproperty bool KeyActions::enabled
+
+ Enables or disables KeyActions' key handling. When not enabled, the
+ KeyActions instance does not respond to any key presses. The item is
+ enabled by default.
+*/
+bool QFxKeyActions::enabled() const
+{
+ return d->enabled;
+}
+
+void QFxKeyActions::setEnabled(bool e)
+{
+ if (d->enabled == e)
+ return;
+
+ d->enabled = e;
+ emit enabledChanged();
+}
+
+/*!
+ \qmlproperty string KeyActions::keyA...keyZ
+
+ The action to take for the given letter.
+
+ The following example sets actions for the 'c' and 'x' keys.
+ \qml
+ KeyActions { keyC: "print('c is for cookie')"; keyX: "print('I like cookies')" }
+ \endqml
+*/
+QString QFxKeyActions::key_A() const
+{
+ return d->keyExpr(Qt::Key_A);
+}
+
+void QFxKeyActions::setKey_A(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_A, s);
+}
+
+QString QFxKeyActions::key_B() const
+{
+ return d->keyExpr(Qt::Key_B);
+}
+
+void QFxKeyActions::setKey_B(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_B, s);
+}
+
+QString QFxKeyActions::key_C() const
+{
+ return d->keyExpr(Qt::Key_C);
+}
+
+void QFxKeyActions::setKey_C(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_C, s);
+}
+
+QString QFxKeyActions::key_D() const
+{
+ return d->keyExpr(Qt::Key_D);
+}
+
+void QFxKeyActions::setKey_D(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_D, s);
+}
+
+QString QFxKeyActions::key_E() const
+{
+ return d->keyExpr(Qt::Key_E);
+}
+
+void QFxKeyActions::setKey_E(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_E, s);
+}
+
+QString QFxKeyActions::key_F() const
+{
+ return d->keyExpr(Qt::Key_F);
+}
+
+void QFxKeyActions::setKey_F(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_F, s);
+}
+
+QString QFxKeyActions::key_G() const
+{
+ return d->keyExpr(Qt::Key_G);
+}
+
+void QFxKeyActions::setKey_G(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_G, s);
+}
+
+QString QFxKeyActions::key_H() const
+{
+ return d->keyExpr(Qt::Key_H);
+}
+
+void QFxKeyActions::setKey_H(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_H, s);
+}
+
+QString QFxKeyActions::key_I() const
+{
+ return d->keyExpr(Qt::Key_I);
+}
+
+void QFxKeyActions::setKey_I(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_I, s);
+}
+
+QString QFxKeyActions::key_J() const
+{
+ return d->keyExpr(Qt::Key_J);
+}
+
+void QFxKeyActions::setKey_J(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_J, s);
+}
+
+QString QFxKeyActions::key_K() const
+{
+ return d->keyExpr(Qt::Key_K);
+}
+
+void QFxKeyActions::setKey_K(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_K, s);
+}
+
+QString QFxKeyActions::key_L() const
+{
+ return d->keyExpr(Qt::Key_L);
+}
+
+void QFxKeyActions::setKey_L(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_L, s);
+}
+
+QString QFxKeyActions::key_M() const
+{
+ return d->keyExpr(Qt::Key_M);
+}
+
+void QFxKeyActions::setKey_M(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_M, s);
+}
+
+QString QFxKeyActions::key_N() const
+{
+ return d->keyExpr(Qt::Key_N);
+}
+
+void QFxKeyActions::setKey_N(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_N, s);
+}
+
+QString QFxKeyActions::key_O() const
+{
+ return d->keyExpr(Qt::Key_O);
+}
+
+void QFxKeyActions::setKey_O(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_O, s);
+}
+
+QString QFxKeyActions::key_P() const
+{
+ return d->keyExpr(Qt::Key_P);
+}
+
+void QFxKeyActions::setKey_P(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_P, s);
+}
+
+QString QFxKeyActions::key_Q() const
+{
+ return d->keyExpr(Qt::Key_Q);
+}
+
+void QFxKeyActions::setKey_Q(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Q, s);
+}
+
+QString QFxKeyActions::key_R() const
+{
+ return d->keyExpr(Qt::Key_R);
+}
+
+void QFxKeyActions::setKey_R(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_R, s);
+}
+
+QString QFxKeyActions::key_S() const
+{
+ return d->keyExpr(Qt::Key_S);
+}
+
+void QFxKeyActions::setKey_S(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_S, s);
+}
+
+QString QFxKeyActions::key_T() const
+{
+ return d->keyExpr(Qt::Key_T);
+}
+
+void QFxKeyActions::setKey_T(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_T, s);
+}
+
+QString QFxKeyActions::key_U() const
+{
+ return d->keyExpr(Qt::Key_U);
+}
+
+void QFxKeyActions::setKey_U(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_U, s);
+}
+
+QString QFxKeyActions::key_V() const
+{
+ return d->keyExpr(Qt::Key_V);
+}
+
+void QFxKeyActions::setKey_V(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_V, s);
+}
+
+QString QFxKeyActions::key_W() const
+{
+ return d->keyExpr(Qt::Key_W);
+}
+
+void QFxKeyActions::setKey_W(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_W, s);
+}
+
+QString QFxKeyActions::key_X() const
+{
+ return d->keyExpr(Qt::Key_X);
+}
+
+void QFxKeyActions::setKey_X(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_X, s);
+}
+
+QString QFxKeyActions::key_Y() const
+{
+ return d->keyExpr(Qt::Key_Y);
+}
+
+void QFxKeyActions::setKey_Y(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Y, s);
+}
+
+QString QFxKeyActions::key_Z() const
+{
+ return d->keyExpr(Qt::Key_Z);
+}
+
+void QFxKeyActions::setKey_Z(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Z, s);
+}
+
+
+/*!
+ \qmlproperty string KeyActions::leftArrow
+ \qmlproperty string KeyActions::rightArrow
+ \qmlproperty string KeyActions::upArrow
+ \qmlproperty string KeyActions::downArrow
+
+ The action to take for the given arrow key.
+
+ The following example sets actions for the left and right arrow keys.
+ \qml
+ KeyActions { leftArrow: "print('You pressed left')"; rightArrow: "print('You pressed right')" }
+ \endqml
+*/
+
+QString QFxKeyActions::key_Left() const
+{
+ return d->keyExpr(Qt::Key_Left);
+}
+
+void QFxKeyActions::setKey_Left(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Left, s);
+}
+
+QString QFxKeyActions::key_Right() const
+{
+ return d->keyExpr(Qt::Key_Right);
+}
+
+void QFxKeyActions::setKey_Right(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Right, s);
+}
+
+QString QFxKeyActions::key_Up() const
+{
+ return d->keyExpr(Qt::Key_Up);
+}
+
+void QFxKeyActions::setKey_Up(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Up, s);
+}
+
+QString QFxKeyActions::key_Down() const
+{
+ return d->keyExpr(Qt::Key_Down);
+}
+
+void QFxKeyActions::setKey_Down(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Down, s);
+}
+
+/*!
+ \qmlproperty string KeyActions::digit0...digit9
+
+ The action to take for the given number key.
+
+ The following example sets actions for the '5' and '6' keys.
+ \qml
+ KeyActions { digit5: "print('5 is a prime number')"; digit6: "print('6 is a composite number')"; focus: true }
+ \endqml
+*/
+
+QString QFxKeyActions::key_0() const
+{
+ return d->keyExpr(Qt::Key_0);
+}
+
+void QFxKeyActions::setKey_0(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_0, s);
+}
+
+QString QFxKeyActions::key_1() const
+{
+ return d->keyExpr(Qt::Key_1);
+}
+
+void QFxKeyActions::setKey_1(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_1, s);
+}
+
+QString QFxKeyActions::key_2() const
+{
+ return d->keyExpr(Qt::Key_2);
+}
+
+void QFxKeyActions::setKey_2(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_2, s);
+}
+
+QString QFxKeyActions::key_3() const
+{
+ return d->keyExpr(Qt::Key_3);
+}
+
+void QFxKeyActions::setKey_3(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_3, s);
+}
+
+QString QFxKeyActions::key_4() const
+{
+ return d->keyExpr(Qt::Key_4);
+}
+
+void QFxKeyActions::setKey_4(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_4, s);
+}
+
+QString QFxKeyActions::key_5() const
+{
+ return d->keyExpr(Qt::Key_5);
+}
+
+void QFxKeyActions::setKey_5(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_5, s);
+}
+
+QString QFxKeyActions::key_6() const
+{
+ return d->keyExpr(Qt::Key_6);
+}
+
+void QFxKeyActions::setKey_6(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_6, s);
+}
+
+QString QFxKeyActions::key_7() const
+{
+ return d->keyExpr(Qt::Key_7);
+}
+
+void QFxKeyActions::setKey_7(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_7, s);
+}
+
+QString QFxKeyActions::key_8() const
+{
+ return d->keyExpr(Qt::Key_8);
+}
+
+void QFxKeyActions::setKey_8(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_8, s);
+}
+
+QString QFxKeyActions::key_9() const
+{
+ return d->keyExpr(Qt::Key_9);
+}
+
+void QFxKeyActions::setKey_9(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_9, s);
+}
+
+QString QFxKeyActions::key_Asterisk() const
+{
+ return d->keyExpr(Qt::Key_Asterisk);
+}
+
+void QFxKeyActions::setKey_Asterisk(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Asterisk, s);
+}
+
+QString QFxKeyActions::key_Escape() const
+{
+ return d->keyExpr(Qt::Key_Escape);
+}
+
+void QFxKeyActions::setKey_Escape(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Escape, s);
+}
+
+QString QFxKeyActions::key_Return() const
+{
+ return d->keyExpr(Qt::Key_Return);
+}
+
+void QFxKeyActions::setKey_Return(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Return, s);
+}
+
+QString QFxKeyActions::key_Enter() const
+{
+ return d->keyExpr(Qt::Key_Enter);
+}
+
+void QFxKeyActions::setKey_Enter(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Enter, s);
+}
+
+QString QFxKeyActions::key_Delete() const
+{
+ return d->keyExpr(Qt::Key_Delete);
+}
+
+void QFxKeyActions::setKey_Delete(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Delete, s);
+}
+
+QString QFxKeyActions::key_Space() const
+{
+ return d->keyExpr(Qt::Key_Space);
+}
+
+void QFxKeyActions::setKey_Space(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Space, s);
+}
+
+/*!
+ \qmlproperty string KeyActions::escape
+ \qmlproperty string KeyActions::keyReturn
+ \qmlproperty string KeyActions::enter
+ \qmlproperty string KeyActions::delete
+ \qmlproperty string KeyActions::space
+
+ The action to take for the given utility key.
+
+ The following example sets an action for the space key.
+ \qml
+ KeyActions { space: "print('Space pressed')" }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string KeyActions::back
+ \qmlproperty string KeyActions::select
+ \qmlproperty string KeyActions::yes
+ \qmlproperty string KeyActions::no
+ \qmlproperty string KeyActions::context1
+ \qmlproperty string KeyActions::context2
+ \qmlproperty string KeyActions::context3
+ \qmlproperty string KeyActions::context4
+ \qmlproperty string KeyActions::call
+ \qmlproperty string KeyActions::hangup
+ \qmlproperty string KeyActions::flip
+
+ The action to take for the given device key.
+
+ The following example sets an action for the hangup key.
+ \qml
+ KeyActions { hangup: "print('Go away now')" }
+ \endqml
+*/
+
+QString QFxKeyActions::key_Back() const
+{
+ return d->keyExpr(Qt::Key_Back);
+}
+
+void QFxKeyActions::setKey_Back(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Back, s);
+}
+
+QString QFxKeyActions::key_Select() const
+{
+ return d->keyExpr(Qt::Key_Select);
+}
+
+void QFxKeyActions::setKey_Select(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Select, s);
+}
+
+QString QFxKeyActions::key_Yes() const
+{
+ return d->keyExpr(Qt::Key_Yes);
+}
+
+void QFxKeyActions::setKey_Yes(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Yes, s);
+}
+
+QString QFxKeyActions::key_No() const
+{
+ return d->keyExpr(Qt::Key_No);
+}
+
+void QFxKeyActions::setKey_No(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_No, s);
+}
+
+QString QFxKeyActions::key_Context1() const
+{
+ return d->keyExpr(Qt::Key_Context1);
+}
+
+void QFxKeyActions::setKey_Context1(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context1, s);
+}
+
+QString QFxKeyActions::key_Context2() const
+{
+ return d->keyExpr(Qt::Key_Context2);
+}
+
+void QFxKeyActions::setKey_Context2(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context2, s);
+}
+
+QString QFxKeyActions::key_Context3() const
+{
+ return d->keyExpr(Qt::Key_Context3);
+}
+
+void QFxKeyActions::setKey_Context3(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context3, s);
+}
+
+QString QFxKeyActions::key_Context4() const
+{
+ return d->keyExpr(Qt::Key_Context4);
+}
+
+void QFxKeyActions::setKey_Context4(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context4, s);
+}
+
+QString QFxKeyActions::key_Call() const
+{
+ return d->keyExpr(Qt::Key_Call);
+}
+
+void QFxKeyActions::setKey_Call(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Call, s);
+}
+
+QString QFxKeyActions::key_Hangup() const
+{
+ return d->keyExpr(Qt::Key_Hangup);
+}
+
+void QFxKeyActions::setKey_Hangup(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Hangup, s);
+}
+
+QString QFxKeyActions::key_Flip() const
+{
+ return d->keyExpr(Qt::Key_Flip);
+}
+
+void QFxKeyActions::setKey_Flip(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Flip, s);
+}
+
+/*!
+ \qmlproperty string KeyActions::any
+
+ The action to take for any key not otherwise handled.
+*/
+QString QFxKeyActions::key_Any() const
+{
+ return d->keyExpr(Qt::Key_unknown);
+}
+
+void QFxKeyActions::setKey_Any(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_unknown, s);
+}
+
+void QFxKeyActions::keyPressEvent(QKeyEvent *event)
+{
+ Qt::Key key = (Qt::Key)event->key();
+ if (d->enabled && d->key(key)) {
+ QmlExpression b(qmlContext(this), d->action(key), this);
+ b.value();
+ event->accept();
+ } else {
+ QFxItem::keyPressEvent(event);
+ }
+}
+
+void QFxKeyActions::keyReleaseEvent(QKeyEvent *event)
+{
+ Qt::Key key = (Qt::Key)event->key();
+ if (d->enabled && d->key(key)) {
+ event->accept();
+ } else {
+ QFxItem::keyReleaseEvent(event);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxkeyactions.h b/src/declarative/fx/qfxkeyactions.h
new file mode 100644
index 0000000..cea992a
--- /dev/null
+++ b/src/declarative/fx/qfxkeyactions.h
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXKEYACTIONS_H
+#define QFXKEYACTIONS_H
+
+#include <QtCore/QObject>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxKeyActionsPrivate;
+class Q_DECLARATIVE_EXPORT QFxKeyActions : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QString keyA READ key_A WRITE setKey_A)
+ Q_PROPERTY(QString keyB READ key_B WRITE setKey_B)
+ Q_PROPERTY(QString keyC READ key_C WRITE setKey_C)
+ Q_PROPERTY(QString keyD READ key_D WRITE setKey_D)
+ Q_PROPERTY(QString keyE READ key_E WRITE setKey_E)
+ Q_PROPERTY(QString keyF READ key_F WRITE setKey_F)
+ Q_PROPERTY(QString keyG READ key_G WRITE setKey_G)
+ Q_PROPERTY(QString keyH READ key_H WRITE setKey_H)
+ Q_PROPERTY(QString keyI READ key_I WRITE setKey_I)
+ Q_PROPERTY(QString keyJ READ key_J WRITE setKey_J)
+ Q_PROPERTY(QString keyK READ key_K WRITE setKey_K)
+ Q_PROPERTY(QString keyL READ key_L WRITE setKey_L)
+ Q_PROPERTY(QString keyM READ key_M WRITE setKey_M)
+ Q_PROPERTY(QString keyN READ key_N WRITE setKey_N)
+ Q_PROPERTY(QString keyO READ key_O WRITE setKey_O)
+ Q_PROPERTY(QString keyP READ key_P WRITE setKey_P)
+ Q_PROPERTY(QString keyQ READ key_Q WRITE setKey_Q)
+ Q_PROPERTY(QString keyR READ key_R WRITE setKey_R)
+ Q_PROPERTY(QString keyS READ key_S WRITE setKey_S)
+ Q_PROPERTY(QString keyT READ key_T WRITE setKey_T)
+ Q_PROPERTY(QString keyU READ key_U WRITE setKey_U)
+ Q_PROPERTY(QString keyV READ key_V WRITE setKey_V)
+ Q_PROPERTY(QString keyW READ key_W WRITE setKey_W)
+ Q_PROPERTY(QString keyX READ key_X WRITE setKey_X)
+ Q_PROPERTY(QString keyY READ key_Y WRITE setKey_Y)
+ Q_PROPERTY(QString keyZ READ key_Z WRITE setKey_Z)
+ Q_PROPERTY(QString leftArrow READ key_Left WRITE setKey_Left)
+ Q_PROPERTY(QString rightArrow READ key_Right WRITE setKey_Right)
+ Q_PROPERTY(QString upArrow READ key_Up WRITE setKey_Up)
+ Q_PROPERTY(QString downArrow READ key_Down WRITE setKey_Down)
+ Q_PROPERTY(QString digit0 READ key_0 WRITE setKey_0)
+ Q_PROPERTY(QString digit1 READ key_1 WRITE setKey_1)
+ Q_PROPERTY(QString digit2 READ key_2 WRITE setKey_2)
+ Q_PROPERTY(QString digit3 READ key_3 WRITE setKey_3)
+ Q_PROPERTY(QString digit4 READ key_4 WRITE setKey_4)
+ Q_PROPERTY(QString digit5 READ key_5 WRITE setKey_5)
+ Q_PROPERTY(QString digit6 READ key_6 WRITE setKey_6)
+ Q_PROPERTY(QString digit7 READ key_7 WRITE setKey_7)
+ Q_PROPERTY(QString digit8 READ key_8 WRITE setKey_8)
+ Q_PROPERTY(QString digit9 READ key_9 WRITE setKey_9)
+ Q_PROPERTY(QString asterisk READ key_Asterisk WRITE setKey_Asterisk)
+ Q_PROPERTY(QString escape READ key_Escape WRITE setKey_Escape)
+ Q_PROPERTY(QString return READ key_Return WRITE setKey_Return)
+ Q_PROPERTY(QString enter READ key_Enter WRITE setKey_Enter)
+ Q_PROPERTY(QString delete READ key_Delete WRITE setKey_Delete)
+ Q_PROPERTY(QString space READ key_Space WRITE setKey_Space)
+ Q_PROPERTY(QString back READ key_Back WRITE setKey_Back)
+ Q_PROPERTY(QString select READ key_Select WRITE setKey_Select)
+ Q_PROPERTY(QString yes READ key_Yes WRITE setKey_Yes)
+ Q_PROPERTY(QString no READ key_No WRITE setKey_No)
+ Q_PROPERTY(QString context1 READ key_Context1 WRITE setKey_Context1)
+ Q_PROPERTY(QString context2 READ key_Context2 WRITE setKey_Context2)
+ Q_PROPERTY(QString context3 READ key_Context3 WRITE setKey_Context3)
+ Q_PROPERTY(QString context4 READ key_Context4 WRITE setKey_Context4)
+ Q_PROPERTY(QString call READ key_Call WRITE setKey_Call)
+ Q_PROPERTY(QString hangup READ key_Hangup WRITE setKey_Hangup)
+ Q_PROPERTY(QString flip READ key_Flip WRITE setKey_Flip)
+ Q_PROPERTY(QString any READ key_Any WRITE setKey_Any)
+
+public:
+ QFxKeyActions(QFxItem *parent=0);
+ virtual ~QFxKeyActions();
+
+ bool enabled() const;
+ void setEnabled(bool);
+
+ QString key_A() const;
+ void setKey_A(const QString &);
+
+ QString key_B() const;
+ void setKey_B(const QString &);
+
+ QString key_C() const;
+ void setKey_C(const QString &);
+
+ QString key_D() const;
+ void setKey_D(const QString &);
+
+ QString key_E() const;
+ void setKey_E(const QString &);
+
+ QString key_F() const;
+ void setKey_F(const QString &);
+
+ QString key_G() const;
+ void setKey_G(const QString &);
+
+ QString key_H() const;
+ void setKey_H(const QString &);
+
+ QString key_I() const;
+ void setKey_I(const QString &);
+
+ QString key_J() const;
+ void setKey_J(const QString &);
+
+ QString key_K() const;
+ void setKey_K(const QString &);
+
+ QString key_L() const;
+ void setKey_L(const QString &);
+
+ QString key_M() const;
+ void setKey_M(const QString &);
+
+ QString key_N() const;
+ void setKey_N(const QString &);
+
+ QString key_O() const;
+ void setKey_O(const QString &);
+
+ QString key_P() const;
+ void setKey_P(const QString &);
+
+ QString key_Q() const;
+ void setKey_Q(const QString &);
+
+ QString key_R() const;
+ void setKey_R(const QString &);
+
+ QString key_S() const;
+ void setKey_S(const QString &);
+
+ QString key_T() const;
+ void setKey_T(const QString &);
+
+ QString key_U() const;
+ void setKey_U(const QString &);
+
+ QString key_V() const;
+ void setKey_V(const QString &);
+
+ QString key_W() const;
+ void setKey_W(const QString &);
+
+ QString key_X() const;
+ void setKey_X(const QString &);
+
+ QString key_Y() const;
+ void setKey_Y(const QString &);
+
+ QString key_Z() const;
+ void setKey_Z(const QString &);
+
+ QString key_Left() const;
+ void setKey_Left(const QString &);
+
+ QString key_Right() const;
+ void setKey_Right(const QString &);
+
+ QString key_Up() const;
+ void setKey_Up(const QString &);
+
+ QString key_Down() const;
+ void setKey_Down(const QString &);
+
+ QString key_0() const;
+ void setKey_0(const QString &);
+
+ QString key_1() const;
+ void setKey_1(const QString &);
+
+ QString key_2() const;
+ void setKey_2(const QString &);
+
+ QString key_3() const;
+ void setKey_3(const QString &);
+
+ QString key_4() const;
+ void setKey_4(const QString &);
+
+ QString key_5() const;
+ void setKey_5(const QString &);
+
+ QString key_6() const;
+ void setKey_6(const QString &);
+
+ QString key_7() const;
+ void setKey_7(const QString &);
+
+ QString key_8() const;
+ void setKey_8(const QString &);
+
+ QString key_9() const;
+ void setKey_9(const QString &);
+
+ QString key_Asterisk() const;
+ void setKey_Asterisk(const QString &);
+
+ QString key_Escape() const;
+ void setKey_Escape(const QString &);
+
+ QString key_Return() const;
+ void setKey_Return(const QString &);
+
+ QString key_Enter() const;
+ void setKey_Enter(const QString &);
+
+ QString key_Delete() const;
+ void setKey_Delete(const QString &);
+
+ QString key_Space() const;
+ void setKey_Space(const QString &);
+
+ QString key_Back() const;
+ void setKey_Back(const QString &);
+
+ QString key_Select() const;
+ void setKey_Select(const QString &);
+
+ QString key_Yes() const;
+ void setKey_Yes(const QString &);
+
+ QString key_No() const;
+ void setKey_No(const QString &);
+
+ QString key_Context1() const;
+ void setKey_Context1(const QString &);
+
+ QString key_Context2() const;
+ void setKey_Context2(const QString &);
+
+ QString key_Context3() const;
+ void setKey_Context3(const QString &);
+
+ QString key_Context4() const;
+ void setKey_Context4(const QString &);
+
+ QString key_Call() const;
+ void setKey_Call(const QString &);
+
+ QString key_Hangup() const;
+ void setKey_Hangup(const QString &);
+
+ QString key_Flip() const;
+ void setKey_Flip(const QString &);
+
+ QString key_Any() const;
+ void setKey_Any(const QString &);
+
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+
+Q_SIGNALS:
+ void enabledChanged();
+
+private:
+ Q_DISABLE_COPY(QFxKeyActions)
+ QFxKeyActionsPrivate *d;
+};
+
+QML_DECLARE_TYPE(QFxKeyActions)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXKEYACTIONS_H
diff --git a/src/declarative/fx/qfxkeyproxy.cpp b/src/declarative/fx/qfxkeyproxy.cpp
new file mode 100644
index 0000000..e80f2c7
--- /dev/null
+++ b/src/declarative/fx/qfxkeyproxy.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxkeyproxy.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxKeyProxy,KeyProxy)
+
+/*!
+ \qmlclass KeyProxy
+ \brief The KeyProxy item proxies key presses to a number of other items.
+ \inherits Item
+
+*/
+
+/*!
+ \internal
+ \class QFxKeyProxy
+ \brief The QFxKeyProxy class proxies key presses to a number of other items.
+ \ingroup group_utility
+*/
+
+class QFxKeyProxyPrivate
+{
+public:
+ QList<QFxItem *> targets;
+};
+
+QFxKeyProxy::QFxKeyProxy(QFxItem *parent)
+: QFxItem(parent), d(new QFxKeyProxyPrivate)
+{
+}
+
+QFxKeyProxy::~QFxKeyProxy()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \qmlproperty list<Item> KeyProxy::targets
+
+ The proxy targets.
+*/
+
+/*!
+ \property QFxKeyProxy::targets
+ \brief the proxy targets.
+*/
+
+QList<QFxItem *> *QFxKeyProxy::targets() const
+{
+ return &d->targets;
+}
+
+void QFxKeyProxy::keyPressEvent(QKeyEvent *e)
+{
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QSimpleCanvasItem *i = canvas()->focusItem(d->targets.at(ii));
+ if (i)
+ i->keyPressEvent(e);
+ if (e->isAccepted())
+ return;
+ }
+}
+
+void QFxKeyProxy::keyReleaseEvent(QKeyEvent *e)
+{
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QSimpleCanvasItem *i = canvas()->focusItem(d->targets.at(ii));
+ if (i)
+ i->keyReleaseEvent(e);
+ if (e->isAccepted())
+ return;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxkeyproxy.h b/src/declarative/fx/qfxkeyproxy.h
new file mode 100644
index 0000000..38cff7a
--- /dev/null
+++ b/src/declarative/fx/qfxkeyproxy.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXKEYPROXY_H
+#define QFXKEYPROXY_H
+
+#include <QtDeclarative/qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxKeyProxyPrivate;
+class Q_DECLARATIVE_EXPORT QFxKeyProxy : public QFxItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<QFxItem *> *targets READ targets)
+public:
+ QFxKeyProxy(QFxItem *parent=0);
+ virtual ~QFxKeyProxy();
+
+ QList<QFxItem *> *targets() const;
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+
+private:
+ Q_DISABLE_COPY(QFxKeyProxy)
+ QFxKeyProxyPrivate *d;
+};
+
+QML_DECLARE_TYPE(QFxKeyProxy)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXKEYPROXY_H
diff --git a/src/declarative/fx/qfxlayouts.cpp b/src/declarative/fx/qfxlayouts.cpp
new file mode 100644
index 0000000..a975778
--- /dev/null
+++ b/src/declarative/fx/qfxlayouts.cpp
@@ -0,0 +1,1082 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QCoreApplication>
+#include "qml.h"
+#include "qmlstate.h"
+#include "qmlstategroup.h"
+#include "qmlstateoperations.h"
+#include "qfxperf.h"
+#include "qfxlayouts.h"
+#include "qfxlayouts_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QFxBaseLayout
+ \brief The QFxBaseLayout class provides a base for QFx layouts.
+
+ To create a QFx Layout, simple subclass QFxBaseLayout and implement
+ doLayout(), which is automatically called when the layout might need
+ updating.
+
+ It is strongly recommended that in your implementation of doLayout()
+ that you use the move, remove and add transitions when those conditions
+ arise.
+
+ \ingroup group_layouts
+*/
+QFxBaseLayout::QFxBaseLayout(AutoUpdateType at, QFxItem *parent)
+ : QFxItem(*(new QFxBaseLayoutPrivate), parent)
+{
+ Q_D(QFxBaseLayout);
+ d->init(at);
+}
+
+QFxBaseLayout::QFxBaseLayout(QFxBaseLayoutPrivate &dd, AutoUpdateType at, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxBaseLayout);
+ d->init(at);
+}
+
+/*!
+ \property QFxBaseLayout::spacing
+ \brief the amount of spacing between items (in px)
+
+ Note that the subclass is repsonsible for ensuring this.
+*/
+int QFxBaseLayout::spacing() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->_spacing;
+}
+
+void QFxBaseLayout::setSpacing(int s)
+{
+ Q_D(QFxBaseLayout);
+ if (s==d->_spacing)
+ return;
+ d->_spacing = s;
+ preLayout();
+}
+
+/*!
+ \property QFxBaseLayout::margin
+ \brief the size of the margin around all items (in px)
+
+*/
+int QFxBaseLayout::margin() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->_margin;
+}
+
+void QFxBaseLayout::setMargin(int s)
+{
+ Q_D(QFxBaseLayout);
+ if (s==d->_margin)
+ return;
+ d->_margin = s;
+ preLayout();
+}
+
+
+/*!
+ \property QFxBaseLayout::move
+ \brief the transition when moving an item.
+
+ \qml
+BaseLayout {
+ id: layout
+ y: 0
+ move: Transition {
+ NumericAnimation {
+ properties: "y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+*/
+QmlTransition *QFxBaseLayout::move() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->moveTransition;
+}
+
+void QFxBaseLayout::setMove(QmlTransition *mt)
+{
+ Q_D(QFxBaseLayout);
+ d->moveTransition = mt;
+}
+
+/*!
+ \property QFxBaseLayout::add
+ \brief the transition when adding an item.
+
+ \qml
+BaseLayout {
+ id: layout
+ y: 0
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+*/
+QmlTransition *QFxBaseLayout::add() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->addTransition;
+}
+
+void QFxBaseLayout::setAdd(QmlTransition *add)
+{
+ Q_D(QFxBaseLayout);
+ d->addTransition = add;
+}
+
+
+/*!
+ \property QFxBaseLayout::remove
+ \brief the transition when removing an item.
+
+ Note that the item may be 'removed' because its opacity is zero. This can make certain
+ transitions difficult to see.
+ \qml
+BaseLayout {
+ id: layout
+ y: 0
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+*/
+QmlTransition *QFxBaseLayout::remove() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->removeTransition;
+}
+
+void QFxBaseLayout::setRemove(QmlTransition *remove)
+{
+ Q_D(QFxBaseLayout);
+ d->removeTransition = remove;
+}
+
+/*!
+ \property QFxBaseLayout::item
+
+ The item that is currently being laid out. Used to target transitions that apply
+ only to the item being laid out, such as in the add transition.
+*/
+
+QFxItem *QFxBaseLayout::layoutItem() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->_layoutItem;
+}
+
+/*!
+ \internal
+*/
+void QFxBaseLayout::setLayoutItem(QFxItem *li)
+{
+ Q_D(QFxBaseLayout);
+ if (li == d->_layoutItem)
+ return;
+ d->_layoutItem = li;
+ emit layoutItemChanged();
+}
+
+void QFxBaseLayout::componentComplete()
+{
+ QFxItem::componentComplete();
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BaseLayoutComponentComplete> cc;
+#endif
+ preLayout();
+}
+
+void QFxBaseLayout::childrenChanged()
+{
+ preLayout();
+}
+
+bool QFxBaseLayout::event(QEvent *e)
+{
+ Q_D(QFxBaseLayout);
+ if (e->type() == QEvent::User) {
+ d->_ep = false;
+ d->_stableItems += d->_newItems;
+ d->_leavingItems.clear();
+ d->_newItems.clear();
+ return true;
+ }
+ return QFxItem::event(e);
+}
+
+/*!
+ Items that have just been added to the layout. This includes invisible items
+ that have turned visible.
+*/
+QSet<QFxItem *>* QFxBaseLayout::newItems()
+{
+ Q_D(QFxBaseLayout);
+ return &d->_newItems;
+}
+
+/*!
+ Items that are visible in the layout, not including ones that have just been added.
+*/
+QSet<QFxItem *>* QFxBaseLayout::items()
+{
+ Q_D(QFxBaseLayout);
+ return &d->_stableItems;
+}
+
+/*!
+ Items that have just left the layout. This includes visible items
+ that have turned invisible.
+*/
+QSet<QFxItem *>* QFxBaseLayout::leavingItems()
+{
+ Q_D(QFxBaseLayout);
+ return &d->_leavingItems;
+}
+
+void QFxBaseLayout::preLayout()
+{
+ Q_D(QFxBaseLayout);
+ if (!isComponentComplete() || d->_movingItem)
+ return;
+
+ if (!d->_ep) {
+ d->_ep = true;
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+ if (d->stateGroup) {
+ delete d->stateGroup; d->stateGroup = 0;
+ }
+ QSet<QFxItem *> allItems;
+ for (int ii = 0; ii < this->QSimpleCanvasItem::children().count(); ++ii) {
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(ii));
+ if (!child)
+ continue;
+ if (!d->_items.contains(child)){
+ QObject::connect(child, SIGNAL(visibleChanged()),
+ this, SLOT(preLayout()));
+ QObject::connect(child, SIGNAL(heightChanged()),
+ this, SLOT(preLayout()));
+ QObject::connect(child, SIGNAL(widthChanged()),
+ this, SLOT(preLayout()));
+ d->_items += child;
+ }
+ if (!child->isVisible()){
+ if (d->_stableItems.contains(child)){
+ d->_leavingItems += child;
+ d->_stableItems -= child;
+ }
+ }else if (!d->_stableItems.contains(child)){
+ d->_newItems+=child;
+ }
+ allItems += child;
+ }
+ QSet<QFxItem *> deletedItems = d->_items - allItems;
+ foreach(QFxItem *child, d->_items){
+ if (!allItems.contains(child)){
+ if (!deletedItems.contains(child)) {
+ QObject::disconnect(child, SIGNAL(visibleChanged()),
+ this, SLOT(preLayout()));
+ QObject::disconnect(child, SIGNAL(heightChanged()),
+ this, SLOT(preLayout()));
+ QObject::disconnect(child, SIGNAL(widthChanged()),
+ this, SLOT(preLayout()));
+ }
+ d->_items -= child;
+ }
+ }
+ d->_animated.clear();
+ doLayout();
+ //Set the layout's size to be the rect containing all children
+ //Also set the margin
+ qreal width=0;
+ qreal height=0;
+ foreach(QFxItem *item, d->_items){
+ if (item->isVisible()){
+ if (!d->_animated.contains(item)){
+ setMovingItem(item);
+ QPointF p(item->x(), item->y());
+ if(d->aut & Horizontal)
+ p.setX(p.x() + d->_margin);
+ if(d->aut & Vertical)
+ p.setY(p.y() + d->_margin);
+ item->setPos(p);
+ setMovingItem(0);
+ }
+ width = qMax(width, item->x() + item->width());
+ height = qMax(height, item->y() + item->height());
+ }
+ }
+ width += d->_margin;
+ height+= d->_margin;
+
+ if (d->aut & Horizontal)
+ setWidth(int(width));
+ else if (itemParent())
+ setImplicitWidth(itemParent()->width());
+ if (d->aut & Vertical)
+ setHeight(int(height));
+ else if (itemParent())
+ setImplicitHeight(itemParent()->height());
+ setLayoutItem(0);
+}
+
+//###This should be considered to move more centrally, as it seems useful
+void QFxBaseLayout::applyTransition(const QList<QPair<QString, QVariant> >& changes,
+ QFxItem* target, QmlTransition* trans)
+{
+ Q_D(QFxBaseLayout);
+ if (!trans||!target)//TODO: if !trans, just apply changes
+ return;
+ setLayoutItem(target);
+ if (d->stateGroup)
+ delete d->stateGroup;
+ d->stateGroup = new QmlStateGroup(this);
+
+ QmlState *state = new QmlState;
+ *(d->stateGroup->statesProperty()) << state;
+ for (int ii=0; ii<changes.size(); ++ii){
+ QmlSetProperty *sp = new QmlSetProperty(state);
+ sp->setObject(target);
+ QVariant val = changes[ii].second;
+ if (d->_margin &&
+ (changes[ii].first == QLatin1String("x") || changes[ii].first == QLatin1String("y"))){
+ val = QVariant(val.toInt() + d->_margin);
+ }
+ sp->setValue(val);
+ sp->setProperty(changes[ii].first);
+ *state << sp;
+ }
+ state->apply(d->stateGroup, trans, 0);
+ d->_animated << target;
+}
+
+void QFxBaseLayout::setMovingItem(QFxItem *i)
+{
+ Q_D(QFxBaseLayout);
+ d->_movingItem = i;
+}
+
+/*!
+ Applies the layout's add transition to the \a target item.\a changes is a list of property,value
+ pairs which will be changed on the target using the add transition.
+*/
+void QFxBaseLayout::applyAdd(const QList<QPair<QString, QVariant> >& changes, QFxItem* target)
+{
+ applyTransition(changes,target, add());
+}
+
+/*!
+ Applies the layout's move transition to the \a target.\a changes is a list of property,value pairs
+ which will be changed on the target using the move transition.
+*/
+void QFxBaseLayout::applyMove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target)
+{
+ applyTransition(changes,target, move());
+}
+
+/*!
+ Applies the layout's remove transition to the \a target item.\a changes is a list of
+ property,value pairs which will be changed on the target using the remove transition.
+*/
+void QFxBaseLayout::applyRemove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target)
+{
+ applyTransition(changes,target, remove());
+}
+
+QML_DEFINE_TYPE(QFxVerticalLayout, VerticalLayout)
+/*!
+ \qmlclass VerticalLayout
+ \brief The VerticalLayout item arranges its children in a vertical layout.
+ \inherits Item
+
+ The VerticalLayout item arranges its child items so that they are vertically
+ aligned and not overlapping. Spacing between items can be added, as can a margin around all the items.
+
+ The below example lays out differently shaped rectangles using a VerticalLayout.
+ \table
+ \row
+ \o \image verticalLayout_example.png
+ \o
+ \qml
+VerticalLayout {
+ spacing: 2
+ Rect { color: "red"; width: 50; height: 50 }
+ Rect { color: "green"; width: 20; height: 50 }
+ Rect { color: "blue"; width: 50; height: 20 }
+}
+ \endqml
+ \endtable
+
+ VerticalLayout also provides for transitions to be set when items are added, moved,
+ or removed in the layout. Adding and removing apply both to items which are deleted
+ or have their position in the document changed so as to no longer be children of the layout,
+ as well as to items which have their opacity set to or from zero so as to appear or disappear.
+
+ \table
+ \row
+ \o \image verticalLayout_transition.gif
+ \o
+ \qml
+VerticalLayout {
+ spacing: 2
+ remove: ...
+ add: ...
+ move: ...
+ ...
+}
+ \endqml
+ \endtable
+
+
+*/
+/*!
+ \qmlproperty Transition VerticalLayout::remove
+ This property holds the transition to apply when removing an item from the layout.
+
+ Removed can mean that either the object has been deleted or reparented, and thus is now longer a child of the layout, or that the object has had its opacity set to zero, and thus is no longer visible.
+
+ Note that if the item counts as removed because its opacity is zero it will not be visible during the transition unless you set the opacity in the transition, like in the below example.
+
+ \table
+ \row
+ \o \image layout-remove.gif
+ \o
+ \qml
+VerticalLayout {
+ id: layout
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+ \endtable
+
+*/
+/*!
+ \qmlproperty Transition VerticalLayout::add
+ This property holds the transition to be applied when adding an item to the layout.
+
+ Added can mean that either the object has been created or reparented, and thus is now a child or the layout, or that the object has had its opacity increased from zero, and thus is now visible.
+
+ \table
+ \row
+ \o \image layout-add.gif
+ \o
+ \qml
+VerticalLayout {
+ id: layout
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+ \endtable
+
+*/
+/*!
+ \qmlproperty Transition VerticalLayout::move
+ This property holds the transition to apply when moving an item within the layout.
+
+ This can happen when other items are added or removed from the layout, or when items resize themselves.
+
+ \table
+ \row
+ \o \image layout-move.gif
+ \o
+ \qml
+VerticalLayout {
+ id: layout
+ move: Transition {
+ NumericAnimation {
+ properties: "y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+ \endtable
+*/
+/*!
+ \qmlproperty Item VerticalLayout::item
+
+ The item that is currently being laid out. Used to target transitions that apply
+ only to the item being laid out, such as in the add transition.
+
+*/
+/*!
+ \qmlproperty int VerticalLayout::spacing
+ \qmlproperty int VerticalLayout::margin
+
+ spacing and margin allow you to control the empty space surrounding
+ items in layouts.
+
+ spacing is the amount in pixels left empty between each adjacent
+ item. margin is the amount in pixels which will be left empty
+ around the inside edge of the layout. Both default to 0.
+
+ The below example places a GridLayout containing a red, a blue and a
+ green rectangle on a gray background. The area the grid layout
+ occupies is colored white. The top layout has a spacing of 2 and a
+ margin of 5, the bottom layout has the defaults of no margin or
+ spacing.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QFxVerticalLayout
+ \brief The QFxVerticalLayout class lines up items vertically.
+ \ingroup group_layouts
+*/
+QFxVerticalLayout::QFxVerticalLayout(QFxItem *parent)
+: QFxBaseLayout(Vertical, parent)
+{
+}
+
+void QFxVerticalLayout::doLayout()
+{
+ int voffset = 0;
+
+ foreach(QFxItem* item, *leavingItems()){
+ if (remove()){
+ QList<QPair<QString,QVariant> > changes;
+ applyRemove(changes, item);
+ }
+ }
+ for (int ii = 0; ii < this->QSimpleCanvasItem::children().count(); ++ii) {
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(ii));
+ if (!child || !child->isVisible())
+ continue;
+
+ bool needMove = (child->y() != voffset || child->x());
+
+ QList<QPair<QString, QVariant> > changes;
+ changes << qMakePair(QString(QLatin1String("y")),QVariant(voffset));
+ changes << qMakePair(QString(QLatin1String("x")),QVariant(0));
+ if (needMove && items()->contains(child) && move()) {
+ applyMove(changes,child);
+ } else if (!items()->contains(child) && add()) {
+ applyAdd(changes,child);
+ } else if (needMove) {
+ setMovingItem(child);
+ child->setY(voffset);
+ setMovingItem(0);
+ }
+ voffset += child->height();
+ voffset += spacing();
+ }
+ setMovingItem(this);
+ setHeight(voffset);
+ setMovingItem(0);
+}
+
+QML_DEFINE_TYPE(QFxHorizontalLayout,HorizontalLayout)
+/*!
+ \qmlclass HorizontalLayout
+ \brief The HorizontalLayout item arranges its children in a horizontal layout.
+ \inherits Item
+
+ The HorizontalLayout item arranges its child items so that they are horizontally aligned and not overlapping. Spacing can be added between the items, and a margin around all items can also be added. It also provides for transitions to be set when items are added, moved, or removed in the layout. Adding and removing apply both to items which are deleted or have their position in the document changed so as to no longer be children of the layout, as well as to items which have their opacity set to or from zero so as to appear or disappear.
+
+ The below example lays out differently shaped rectangles using a HorizontalLayout.
+ \qml
+HorizontalLayout {
+ spacing: 2
+ Rect { color: "red"; width: 50; height: 50 }
+ Rect { color: "green"; width: 20; height: 50 }
+ Rect { color: "blue"; width: 50; height: 20 }
+}
+ \endqml
+ \image horizontalLayout_example.png
+
+*/
+/*!
+ \qmlproperty Transition HorizontalLayout::remove
+ This property holds the transition to apply when removing an item from the layout.
+
+ Removed can mean that either the object has been deleted or reparented, and thus is now longer a child of the layout, or that the object has had its opacity set to zero, and thus is no longer visible.
+
+ Note that if the item counts as removed because its opacity is zero it will not be visible during the transition unless you set the opacity in the transition, like in the below example.
+
+ \qml
+HorizontalLayout {
+ id: layout
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition HorizontalLayout::add
+ This property holds the transition to apply when adding an item to the layout.
+
+ Added can mean that either the object has been created or reparented, and thus is now a child or the layout, or that the object has had its opacity increased from zero, and thus is now visible.
+
+ \qml
+HorizontalLayout {
+ id: layout
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition HorizontalLayout::move
+ This property holds the transition to apply when moving an item within the layout.
+
+ This can happen when other items are added or removed from the layout, or when items resize themselves.
+
+ \qml
+HorizontalLayout {
+ id: layout
+ move: Transition {
+ NumericAnimation {
+ properties: "x"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Item HorizontalLayout::item
+
+ The item that is currently being laid out. Used to target transitions that apply
+ only to the item being laid out, such as in the add transition.
+
+*/
+/*!
+ \qmlproperty int HorizontalLayout::spacing
+
+ The spacing, in pixels, left empty between each adjacent item.
+*/
+/*!
+ \qmlproperty int HorizontalLayout::margin
+
+ The margin size, in pixels, which will be left empty around the inside edge of the layout.
+*/
+/*!
+ \qmlproperty int HorizontalLayout::spacing
+ \qmlproperty int HorizontalLayout::margin
+
+ spacing and margin allow you to control the empty space surrounding items in layouts.
+
+ spacing is the amount in pixels left empty between each adjacent item.
+ margin is the amount in pixels which will be left empty around the inside edge of the layout.
+ Both default to 0.
+
+ The below example places a GridLayout containing a red, a blue and a green rectangle on a gray background. The area the grid layout occupies is colored white. The top layout has a spacing of 2 and a margin of 5, the bottom layout has the defaults of no margin or spacing.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QFxHorizontalLayout
+ \brief The QFxHorizontalLayout class lines up items horizontally.
+ \ingroup group_layouts
+*/
+QFxHorizontalLayout::QFxHorizontalLayout(QFxItem *parent)
+: QFxBaseLayout(Horizontal, parent)
+{
+}
+
+void QFxHorizontalLayout::doLayout()
+{
+ int hoffset = 0;
+
+ foreach(QFxItem* item, *leavingItems()){
+ if (remove()){
+ QList<QPair<QString,QVariant> > changes;
+ applyRemove(changes, item);
+ }
+ }
+ for (int ii = 0; ii < this->QSimpleCanvasItem::children().count(); ++ii) {
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(ii));
+ if (!child || !child->isVisible())
+ continue;
+
+ bool needMove = (child->x() != hoffset || child->y());
+
+ QList<QPair<QString, QVariant> > changes;
+ changes << qMakePair(QString(QLatin1String("x")),QVariant(hoffset));
+ changes << qMakePair(QString(QLatin1String("y")),QVariant(0));
+ if (needMove && items()->contains(child) && move()) {
+ applyMove(changes,child);
+ } else if (!items()->contains(child) && add()) {
+ applyAdd(changes,child);
+ } else if (needMove) {
+ setMovingItem(child);
+ child->setX(hoffset);
+ setMovingItem(0);
+ }
+ hoffset += child->width();
+ hoffset += spacing();
+ }
+ setWidth(hoffset);
+}
+
+QML_DEFINE_TYPE(QFxGridLayout,GridLayout)
+
+/*!
+ \qmlclass GridLayout QFxGridLayout
+ \brief The GridLayout item arranges its children in a grid layout.
+ \inherits Item
+
+ The GridLayout item arranges its child items so that they are
+ aligned in a grid and are not overlapping. Spacing can be added
+ between the items, and a margin around all the items can also be
+ defined. It also provides for transitions to be set when items are
+ added, moved, or removed in the layout. Adding and removing apply
+ both to items which are deleted or have their position in the
+ document changed so as to no longer be children of the layout, as
+ well as to items which have their opacity set to or from zero so
+ as to appear or disappear.
+
+ The GridLayout defaults to using four columns, and as many rows as
+ are necessary to fit all the child items. The number of rows
+ and/or the number of columns can be constrained by setting the rows
+ or columns properties. The grid layout calculates a grid with
+ rectangular cells of sufficient size to hold all items, and then
+ places the items in the cells, going across then down, and
+ positioning each item at the (0,0) corner of the cell. The below
+ example demonstrates this.
+
+ \table
+ \row
+ \o \image gridLayout_example.png
+ \o
+ \qml
+GridLayout {
+ columns: 3
+ spacing: 2
+ Rect { color: "red"; width: 50; height: 50 }
+ Rect { color: "green"; width: 20; height: 50 }
+ Rect { color: "blue"; width: 50; height: 20 }
+ Rect { color: "cyan"; width: 50; height: 50 }
+ Rect { color: "magenta"; width: 10; height: 10 }
+}
+ \endqml
+ \endtable
+*/
+/*!
+ \qmlproperty Transition GridLayout::remove
+ This property holds the transition to apply when removing an item from the layout.
+
+ Removed can mean that either the object has been deleted or
+ reparented, and thus is now longer a child of the layout, or that
+ the object has had its opacity set to zero, and thus is no longer
+ visible.
+
+ Note that if the item counts as removed because its opacity is
+ zero it will not be visible during the transition unless you set
+ the opacity in the transition, like in the below example.
+
+ \qml
+GridLayout {
+ id: layout
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition GridLayout::add
+ This property holds the transition to apply when adding an item to the layout.
+
+ Added can mean that either the object has been created or
+ reparented, and thus is now a child or the layout, or that the
+ object has had its opacity increased from zero, and thus is now
+ visible.
+
+ \qml
+GridLayout {
+ id: layout
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition GridLayout::move
+ This property holds the transition to apply when moving an item within the layout.
+
+ This can happen when other items are added or removed from the layout, or
+ when items resize themselves.
+
+ \qml
+GridLayout {
+ id: layout
+ move: Transition {
+ NumericAnimation {
+ properties: "x,y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Item GridLayout::item
+
+ The item that is currently being laid out. Used to target
+ transitions that apply only to the item being laid out, such as in
+ the add transition.
+
+*/
+/*!
+ \qmlproperty int GridLayout::spacing
+ \qmlproperty int GridLayout::margin
+
+ spacing and margin allow you to control the empty space surrounding
+ items in layouts.
+
+ spacing is the amount in pixels left empty between each adjacent
+ item. margin is the amount in pixels which will be left empty
+ around the inside edge of the layout. Both default to 0.
+
+ The below example places a GridLayout containing a red, a blue and a
+ green rectangle on a gray background. The area the grid layout
+ occupies is colored white. The top layout has a spacing of 2 and a
+ margin of 5, the bottom layout has the defaults of no margin or
+ spacing.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QFxGridLayout
+ \brief The QFxGridLayout class lays out items in a grid.
+ \ingroup group_layouts
+
+*/
+QFxGridLayout::QFxGridLayout(QFxItem *parent) :
+ QFxBaseLayout(Both, parent)
+{
+ _columns=-1;
+ _rows=-1;
+}
+
+/*!
+ \qmlproperty int GridLayout::columns
+ This property holds the number of columns in the grid.
+
+ When the columns property is set the GridLayout will always have
+ that many columns. Note that if you do not have enough items to
+ fill this many columns some columns will be of zero width.
+*/
+
+/*!
+ \qmlproperty int GridLayout::rows
+ This property holds the number of rows in the grid.
+
+ When the rows property is set the GridLayout will always have that
+ many rows. Note that if you do not have enough items to fill this
+ many rows some rows will be of zero width.
+*/
+
+/*!
+ \property QFxGridLayout::columns
+ \brief the number of columns in the grid.
+*/
+
+/*!
+ \property QFxGridLayout::rows
+ \brief the number of rows in the grid.
+*/
+
+void QFxGridLayout::doLayout()
+{
+ int c=_columns,r=_rows;//Actual number of rows/columns
+ int numVisible = items()->size() + newItems()->size();
+ if (_columns==-1 && _rows==-1){
+ c = 4;
+ r = (numVisible+2)/3;
+ }else if (_rows==-1){
+ r = (numVisible+(_columns-1))/_columns;
+ }else if (_columns==-1){
+ c = (numVisible+(_rows-1))/_rows;
+ }
+
+ QList<int> maxColWidth;
+ QList<int> maxRowHeight;
+ int childIndex =0;
+ for (int i=0; i<r; i++){
+ for (int j=0; j<c; j++){
+ if (j==0)
+ maxRowHeight << 0;
+ if (i==0)
+ maxColWidth << 0;
+ if (childIndex == this->QSimpleCanvasItem::children().count())
+ continue;
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(childIndex++));
+ if (!child || !child->isVisible())
+ continue;
+ if (child->width() > maxColWidth[j])
+ maxColWidth[j] = child->width();
+ if (child->height() > maxRowHeight[i])
+ maxRowHeight[i] = child->height();
+ }
+ }
+
+ int xoffset=0;
+ int yoffset=0;
+ int curRow =0;
+ int curCol =0;
+ foreach(QFxItem* item, *leavingItems()){
+ if (remove()){
+ QList<QPair<QString,QVariant> > changes;
+ applyRemove(changes, item);
+ }
+ }
+ foreach(QSimpleCanvasItem* schild, this->QSimpleCanvasItem::children()){
+ QFxItem *child = qobject_cast<QFxItem *>(schild);
+ if (!child || !child->isVisible())
+ continue;
+ bool needMove = (child->x()!=xoffset)||(child->y()!=yoffset);
+ QList<QPair<QString, QVariant> > changes;
+ changes << qMakePair(QString(QLatin1String("x")),QVariant(xoffset));
+ changes << qMakePair(QString(QLatin1String("y")),QVariant(yoffset));
+ if (newItems()->contains(child) && add()) {
+ applyAdd(changes,child);
+ } else if (needMove) {
+ if (move()){
+ applyMove(changes,child);
+ }else{
+ setMovingItem(child);
+ child->setPos(QPointF(xoffset, yoffset));
+ setMovingItem(0);
+ }
+ }
+ xoffset+=maxColWidth[curCol]+spacing();
+ curCol++;
+ curCol%=c;
+ if (!curCol){
+ yoffset+=maxRowHeight[curRow]+spacing();
+ xoffset=0;
+ curRow++;
+ if (curRow>=r)
+ return;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxlayouts.h b/src/declarative/fx/qfxlayouts.h
new file mode 100644
index 0000000..b119d6f
--- /dev/null
+++ b/src/declarative/fx/qfxlayouts.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXLAYOUTS_H
+#define QFXLAYOUTS_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtDeclarative/qfxitem.h>
+#include <QtDeclarative/qmlstate.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxBaseLayoutPrivate;
+
+class Q_DECLARATIVE_EXPORT QFxBaseLayout : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
+ Q_PROPERTY(int margin READ margin WRITE setMargin)
+ Q_PROPERTY(QmlTransition *move READ move WRITE setMove)
+ Q_PROPERTY(QmlTransition *add READ add WRITE setAdd)
+ Q_PROPERTY(QmlTransition *remove READ remove WRITE setRemove)
+ Q_PROPERTY(QFxItem *item READ layoutItem NOTIFY layoutItemChanged)
+public:
+ enum AutoUpdateType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
+ QFxBaseLayout(AutoUpdateType, QFxItem *parent);
+
+ int spacing() const;
+ void setSpacing(int);
+
+ int margin() const;
+ void setMargin(int);
+
+ QmlTransition *move() const;
+ void setMove(QmlTransition *);
+
+ QmlTransition *add() const;
+ void setAdd(QmlTransition *);
+
+ QmlTransition *remove() const;
+ void setRemove(QmlTransition *);
+
+ QFxItem *layoutItem() const;
+
+protected:
+ virtual void componentComplete();
+ virtual void childrenChanged();
+ virtual bool event(QEvent *);
+ QSet<QFxItem *>* newItems();
+ QSet<QFxItem *>* leavingItems();
+ QSet<QFxItem *>* items();
+ void applyAdd(const QList<QPair<QString, QVariant> >& changes, QFxItem* target);
+ void applyMove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target);
+ void applyRemove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target);
+
+Q_SIGNALS:
+ void layoutItemChanged();
+
+protected Q_SLOTS:
+ virtual void doLayout()=0;
+ void setLayoutItem(QFxItem *);
+
+private Q_SLOTS:
+ void preLayout();
+
+protected:
+ QFxBaseLayout(QFxBaseLayoutPrivate &dd, AutoUpdateType at, QFxItem *parent);
+ void setMovingItem(QFxItem *);
+
+private:
+ void applyTransition(const QList<QPair<QString, QVariant> >& changes, QFxItem* target,
+ QmlTransition* transition);
+ Q_DISABLE_COPY(QFxBaseLayout)
+ Q_DECLARE_PRIVATE(QFxBaseLayout)
+};
+
+class Q_DECLARATIVE_EXPORT QFxVerticalLayout : public QFxBaseLayout
+{
+ Q_OBJECT
+public:
+ QFxVerticalLayout(QFxItem *parent=0);
+protected Q_SLOTS:
+ virtual void doLayout();
+private:
+ Q_DISABLE_COPY(QFxVerticalLayout)
+};
+QML_DECLARE_TYPE(QFxVerticalLayout)
+
+class Q_DECLARATIVE_EXPORT QFxHorizontalLayout: public QFxBaseLayout
+{
+ Q_OBJECT
+public:
+ QFxHorizontalLayout(QFxItem *parent=0);
+protected Q_SLOTS:
+ virtual void doLayout();
+private:
+ Q_DISABLE_COPY(QFxHorizontalLayout)
+};
+QML_DECLARE_TYPE(QFxHorizontalLayout)
+
+class Q_DECLARATIVE_EXPORT QFxGridLayout : public QFxBaseLayout
+{
+ Q_OBJECT
+ Q_PROPERTY(int rows READ rows WRITE setRows)
+ Q_PROPERTY(int columns READ columns WRITE setcolumns)
+public:
+ QFxGridLayout(QFxItem *parent=0);
+
+ int rows() const {return _rows;}
+ void setRows(const int rows){_rows = rows;}
+
+ int columns() const {return _columns;}
+ void setcolumns(const int columns){_columns = columns;}
+protected Q_SLOTS:
+ virtual void doLayout();
+
+private:
+ int _rows;
+ int _columns;
+ Q_DISABLE_COPY(QFxGridLayout)
+};
+QML_DECLARE_TYPE(QFxGridLayout)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxlayouts_p.h b/src/declarative/fx/qfxlayouts_p.h
new file mode 100644
index 0000000..77b0ea1
--- /dev/null
+++ b/src/declarative/fx/qfxlayouts_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXLAYOUTS_P_H
+#define QFXLAYOUTS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qfxitem_p.h>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtDeclarative/qfxlayouts.h>
+#include <QtDeclarative/qmlstate.h>
+
+
+QT_BEGIN_NAMESPACE
+class QFxBaseLayoutPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxBaseLayout)
+
+public:
+ QFxBaseLayoutPrivate()
+ : _ep(false), _componentComplete(false), _spacing(0),
+ _margin(0), aut(QFxBaseLayout::None), moveTransition(0), addTransition(0),
+ removeTransition(0), _layoutItem(0), stateGroup(0), _movingItem(0)
+ {
+ }
+
+ void init(QFxBaseLayout::AutoUpdateType at)
+ {
+ aut = at;
+ }
+
+ bool _ep;
+ bool _componentComplete;
+ int _spacing;
+ int _margin;
+ QFxBaseLayout::AutoUpdateType aut;
+ QmlTransition *moveTransition;
+ QmlTransition *addTransition;
+ QmlTransition *removeTransition;
+ QSet<QFxItem *> _items;
+ QSet<QFxItem *> _leavingItems;
+ QSet<QFxItem *> _stableItems;
+ QSet<QFxItem *> _newItems;
+ QSet<QFxItem *> _animated;
+ QFxItem *_layoutItem;
+ QmlStateGroup *stateGroup;
+ QFxItem *_movingItem;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp
new file mode 100644
index 0000000..432c6ac
--- /dev/null
+++ b/src/declarative/fx/qfxlistview.cpp
@@ -0,0 +1,1649 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qfxflickable_p.h"
+#include "qmlfollow.h"
+#include "qlistmodelinterface.h"
+#include "qfxvisualitemmodel.h"
+#include "qfxlistview.h"
+#include <qmlexpression.h>
+
+
+QT_BEGIN_NAMESPACE
+class QFxListViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QFxListViewAttached(QObject *parent)
+ : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+ ~QFxListViewAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(QFxListView *view READ view);
+ QFxListView *view() { return m_view; }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged);
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(QString prevSection READ prevSection NOTIFY prevSectionChanged);
+ QString prevSection() const { return m_prevSection; }
+ void setPrevSection(const QString &sect) {
+ if (m_prevSection != sect) {
+ m_prevSection = sect;
+ emit prevSectionChanged();
+ }
+ }
+
+ Q_PROPERTY(QString section READ section NOTIFY sectionChanged);
+ QString section() const { return m_section; }
+ void setSection(const QString &sect) {
+ if (m_section != sect) {
+ m_section = sect;
+ emit sectionChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged);
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ static QFxListViewAttached *properties(QObject *obj) {
+ QFxListViewAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QFxListViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+signals:
+ void currentItemChanged();
+ void sectionChanged();
+ void prevSectionChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+
+public:
+ QFxListView *m_view;
+ bool m_isCurrent;
+ mutable QString m_section;
+ QString m_prevSection;
+ bool m_delayRemove;
+
+ static QHash<QObject*, QFxListViewAttached*> attachedProperties;
+};
+
+QHash<QObject*, QFxListViewAttached*> QFxListViewAttached::attachedProperties;
+
+//----------------------------------------------------------------------------
+
+class FxListItem
+{
+public:
+ FxListItem(QFxItem *i, QFxListView *v) : item(i), view(v) {
+ attached = QFxListViewAttached::properties(item);
+ attached->m_view = view;
+ }
+ ~FxListItem() {}
+
+ qreal position() const { return (view->orientation() == Qt::Vertical ? item->y() : item->x()); }
+ int size() const { return (view->orientation() == Qt::Vertical ? item->height() : item->width()); }
+ qreal endPosition() const {
+ return (view->orientation() == Qt::Vertical
+ ? item->y() + (item->height() > 0 ? item->height() : 1)
+ : item->x() + (item->width() > 0 ? item->width() : 1)) - 1;
+ }
+ void setPosition(qreal pos) {
+ if (view->orientation() == Qt::Vertical) {
+ item->setY(pos);
+ } else {
+ item->setX(pos);
+ }
+ }
+
+ QFxItem *item;
+ QFxListView *view;
+ QFxListViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QFxListViewPrivate : public QFxFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QFxListView);
+
+public:
+ QFxListViewPrivate()
+ : model(0), currentItem(0), tmpCurrent(0), orient(Qt::Vertical)
+ , visiblePos(0), visibleIndex(0)
+ , averageSize(100), currentIndex(-1), requestedIndex(-1)
+ , currItemMode(QFxListView::Free), snapPos(0), highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
+ , keyPressed(false), ownModel(false), wrap(false), autoHighlight(true)
+ , fixCurrentVisibility(false) {}
+
+ void init();
+ void clear();
+ FxListItem *createItem(int modelIndex);
+ void releaseItem(FxListItem *item);
+
+ FxListItem *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ qreal position() const {
+ Q_Q(const QFxListView);
+ return orient == Qt::Vertical ? q->yPosition() : q->xPosition();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QFxListView);
+ if (orient == Qt::Vertical)
+ q->setYPosition(pos);
+ else
+ q->setXPosition(pos);
+ }
+ int size() const {
+ Q_Q(const QFxListView);
+ return orient == Qt::Vertical ? q->height() : q->width();
+ }
+
+ qreal startPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = visibleItems.first()->position() - visibleIndex * averageSize;
+ return pos;
+ }
+
+ qreal endPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ int invisibleCount = visibleItems.count() - visibleIndex;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ if (visibleItems.at(i)->index != -1) {
+ invisibleCount = model->count() - visibleItems.at(i)->index - 1;
+ break;
+ }
+ }
+ pos = visibleItems.last()->endPosition() + invisibleCount * averageSize;
+ }
+ return pos;
+ }
+
+ qreal positionAt(int modelIndex) const {
+ if (FxListItem *item = visibleItem(modelIndex))
+ return item->position();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ return visibleItems.first()->position() - count * averageSize;
+ } else {
+ int idx = visibleItems.count() - 1;
+ while (idx >= 0 && visibleItems.at(idx)->index == -1)
+ --idx;
+ if (idx < 0)
+ idx = visibleIndex;
+ else
+ idx = visibleItems.at(idx)->index;
+ int count = modelIndex - idx - 1;
+ return visibleItems.last()->endPosition() + count * averageSize + 1;
+ }
+ }
+ return 0;
+ }
+
+ QString sectionAt(int modelIndex) {
+ Q_Q(QFxListView);
+ if (FxListItem *item = visibleItem(modelIndex))
+ return item->attached->section();
+ QString section;
+ if (!sectionExpression.isEmpty())
+ section = model->evaluate(modelIndex, sectionExpression, q).toString();
+ return section;
+ }
+
+ bool isValid() const {
+ return model && model->count() && (!ownModel || model->delegate());
+ }
+
+ int snapIndex() {
+ qreal pos = position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ qreal itemTop = visibleItems[i]->position() - pos;
+ if (itemTop >= snapPos-averageSize/2 && itemTop < snapPos+averageSize/2)
+ return visibleItems[i]->index;
+ }
+ return -1;
+ }
+
+ // map a model index to visibleItems index.
+ // These may differ if removed items are still present in the visible list,
+ // e.g. doing a removal animation
+ int mapFromModel(int modelIndex) const {
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i + visibleIndex;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ bool mapRangeFromModel(int &index, int &count) const {
+ if (index + count < visibleIndex)
+ return false;
+
+ int lastIndex = -1;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index != -1) {
+ lastIndex = listItem->index;
+ break;
+ }
+ }
+
+ if (index > lastIndex)
+ return false;
+
+ int last = qMin(index + count - 1, lastIndex);
+ index = qMax(index, visibleIndex);
+ count = last - index + 1;
+
+ return true;
+ }
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ qDebug() << "index" << visibleIndex << i << listItem->index;
+ abort();
+ }
+ }
+ }
+
+ void refill(qreal from, qreal to);
+ void layout();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void updateSections();
+ void updateCurrentSection();
+ void updateCurrent(int);
+ void updateAverage();
+ void fixupPosition();
+ virtual void fixupY();
+ virtual void fixupX();
+
+ QFxVisualItemModel *model;
+ QVariant modelVariant;
+ QList<FxListItem*> visibleItems;
+ QHash<QFxItem*,int> unrequestedItems;
+ FxListItem *currentItem;
+ QFxItem *tmpCurrent;
+ Qt::Orientation orient;
+ int visiblePos;
+ int visibleIndex;
+ qreal averageSize;
+ int currentIndex;
+ int requestedIndex;
+ QFxListView::CurrentItemPositioning currItemMode;
+ int snapPos;
+ QmlComponent *highlightComponent;
+ FxListItem *highlight;
+ FxListItem *trackedItem;
+ QFxItem *activeItem; //XXX fix
+ enum MovementReason { Other, Key, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QmlFollow *highlightPosAnimator;
+ QmlFollow *highlightSizeAnimator;
+ QString sectionExpression;
+ QString currentSection;
+
+ int keyPressed : 1;
+ int ownModel : 1;
+ int wrap : 1;
+ int autoHighlight : 1;
+ int fixCurrentVisibility : 1;
+};
+
+void QFxListViewPrivate::init()
+{
+ Q_Q(QFxListView);
+ q->setOptions(QFxListView::IsFocusRealm);
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(refill()));
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(refill()));
+}
+
+void QFxListViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visiblePos = 0;
+ visibleIndex = 0;
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
+ createHighlight();
+ trackedItem = 0;
+}
+
+FxListItem *QFxListViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QFxListView);
+ // create object
+ requestedIndex = modelIndex;
+ FxListItem *listItem = 0;
+ if (QFxItem *item = model->item(modelIndex, false)) {
+ listItem = new FxListItem(item, q);
+ listItem->index = modelIndex;
+ // initialise attached properties
+ if (!sectionExpression.isEmpty()) {
+ QmlExpression e(qmlContext(listItem->item), sectionExpression, q);
+ e.setTrackChange(false);
+ listItem->attached->m_section = e.value().toString();
+ if (modelIndex > 0) {
+ if (FxListItem *item = visibleItem(modelIndex-1))
+ listItem->attached->m_prevSection = item->attached->section();
+ else
+ listItem->attached->m_prevSection = sectionAt(modelIndex-1);
+ }
+ }
+ // complete
+ model->completeItem();
+ listItem->item->setZ(modelIndex + 1);
+ listItem->item->setParent(q->viewport());
+ if (orient == Qt::Vertical)
+ QObject::connect(listItem->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
+ else
+ QObject::connect(listItem->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
+ }
+ requestedIndex = -1;
+
+ return listItem;
+}
+
+void QFxListViewPrivate::releaseItem(FxListItem *item)
+{
+ Q_Q(QFxListView);
+ if (!item)
+ return;
+ if (orient == Qt::Vertical)
+ QObject::disconnect(item->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
+ else
+ QObject::disconnect(item->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
+ if (trackedItem == item) {
+ const char *notifier1 = orient == Qt::Vertical ? SIGNAL(topChanged()) : SIGNAL(leftChanged());
+ const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+ QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ delete item;
+}
+
+void QFxListViewPrivate::refill(qreal from, qreal to)
+{
+ Q_Q(QFxListView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+ from -= buffer;
+ to += buffer;
+ int modelIndex = 0;
+ qreal itemEnd = visiblePos-1;
+ if (!visibleItems.isEmpty()) {
+ visiblePos = visibleItems.first()->position();
+ itemEnd = visibleItems.last()->endPosition();
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+
+ bool changed = false;
+ FxListItem *item = 0;
+ int pos = itemEnd + 1;
+ while (modelIndex < model->count() && pos <= to) {
+ //qDebug() << "refill: append item" << modelIndex;
+ if (!(item = createItem(modelIndex)))
+ break;
+ item->setPosition(pos);
+ pos += item->size();
+ visibleItems.append(item);
+ ++modelIndex;
+ changed = true;
+ }
+ while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > from) {
+ //qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+ if (!(item = createItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ visiblePos -= item->size();
+ item->setPosition(visiblePos);
+ visibleItems.prepend(item);
+ changed = true;
+ }
+
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < from) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > to) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ if (changed) {
+ if (visibleItems.count())
+ visiblePos = visibleItems.first()->position();
+ updateAverage();
+ if (!sectionExpression.isEmpty())
+ updateCurrentSection();
+ if (orient == Qt::Vertical)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QFxListViewPrivate::layout()
+{
+ Q_Q(QFxListView);
+ if (!visibleItems.isEmpty()) {
+ int oldEnd = visibleItems.last()->endPosition();
+ int pos = visibleItems.first()->endPosition() + 1;
+ for (int i=1; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ item->setPosition(pos);
+ pos += item->size();
+ }
+ // move current item if it is after the visible items.
+ if (currentItem && currentIndex > visibleItems.last()->index)
+ currentItem->setPosition(currentItem->position() + (visibleItems.last()->endPosition() - oldEnd));
+ }
+ if (!isValid())
+ return;
+ q->refill();
+ q->trackedPositionChanged();
+ updateHighlight();
+ if (orient == Qt::Vertical) {
+ fixupY();
+ q->setViewportHeight(endPosition() - startPosition());
+ } else {
+ fixupX();
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+ updateUnrequestedPositions();
+}
+
+void QFxListViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QFxListView);
+ QHash<QFxItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QFxListViewPrivate::updateUnrequestedPositions()
+{
+ QHash<QFxItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ if (visibleItem(*it))
+ continue;
+ if (orient == Qt::Vertical)
+ it.key()->setY(positionAt(*it));
+ else
+ it.key()->setX(positionAt(*it));
+ }
+}
+
+void QFxListViewPrivate::updateTrackedItem()
+{
+ Q_Q(QFxListView);
+ FxListItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ const char *notifier1 = orient == Qt::Vertical ? SIGNAL(topChanged()) : SIGNAL(leftChanged());
+ const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ q->trackedPositionChanged();
+ }
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QFxListViewPrivate::createHighlight()
+{
+ Q_Q(QFxListView);
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ delete highlight->item;
+ delete highlight;
+ highlight = 0;
+ delete highlightPosAnimator;
+ delete highlightSizeAnimator;
+ highlightPosAnimator = 0;
+ highlightSizeAnimator = 0;
+ }
+
+ if (currentItem) {
+ QFxItem *item = 0;
+ if (highlightComponent) {
+ QmlContext *highlightContext = new QmlContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ highlightContext->setParent(nobj);
+ item = qobject_cast<QFxItem *>(nobj);
+ if (!item) {
+ delete nobj;
+ } else {
+ item->setParent(q->viewport());
+ }
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QFxItem;
+ item->setParent(q->viewport());
+ }
+ if (item) {
+ highlight = new FxListItem(item, q);
+ const QLatin1String posProp(orient == Qt::Vertical ? "y" : "x");
+ highlightPosAnimator = new QmlFollow(q);
+ highlightPosAnimator->setTarget(QmlMetaProperty(highlight->item, posProp));
+ highlightPosAnimator->setSpring(3);
+ highlightPosAnimator->setDamping(0.3);
+ highlightPosAnimator->setEnabled(autoHighlight);
+ const QLatin1String sizeProp(orient == Qt::Vertical ? "height" : "width");
+ highlightSizeAnimator = new QmlFollow(q);
+ highlightSizeAnimator->setTarget(QmlMetaProperty(highlight->item, sizeProp));
+ highlightSizeAnimator->setEnabled(autoHighlight);
+ }
+ }
+}
+
+void QFxListViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ updateTrackedItem();
+ if (currentItem && autoHighlight && highlight) {
+ // auto-update highlight
+ highlightPosAnimator->setSourceValue(currentItem->position());
+ highlightSizeAnimator->setSourceValue(currentItem->size());
+ if (orient == Qt::Vertical) {
+ if (highlight->item->width() == 0)
+ highlight->item->setWidth(currentItem->item->width());
+ } else {
+ if (highlight->item->height() == 0)
+ highlight->item->setHeight(currentItem->item->height());
+ }
+ }
+}
+
+void QFxListViewPrivate::updateSections()
+{
+ if (!sectionExpression.isEmpty()) {
+ QString prevSection;
+ if (visibleIndex > 0)
+ prevSection = sectionAt(visibleIndex-1);
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ QFxListViewAttached *attached = visibleItems.at(i)->attached;
+ attached->setPrevSection(prevSection);
+ prevSection = attached->section();
+ }
+ }
+}
+
+void QFxListViewPrivate::updateCurrentSection()
+{
+ if (sectionExpression.isEmpty() || visibleItems.isEmpty()) {
+ currentSection = QString();
+ return;
+ }
+ int index = 0;
+ while (visibleItems.at(index)->endPosition() < position() && index < visibleItems.count())
+ ++index;
+
+ if (index < visibleItems.count())
+ currentSection = visibleItems.at(index)->attached->section();
+ else
+ currentSection = visibleItems.first()->attached->section();
+}
+
+void QFxListViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QFxListView);
+ if (!isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
+ updateHighlight();
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+
+ if (tmpCurrent) {
+ delete tmpCurrent;
+ tmpCurrent = 0;
+ }
+ FxListItem *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ fixCurrentVisibility = true;
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ if (modelIndex == visibleIndex - 1) {
+ // We can calculate exact postion in this case
+ currentItem->setPosition(visibleItems.first()->position() - currentItem->size());
+ } else {
+ // Create current item now and position as best we can.
+ // Its position will be corrected when it becomes visible.
+ currentItem->setPosition(positionAt(modelIndex));
+ }
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ // Release the old current item
+ releaseItem(oldCurrentItem);
+}
+
+void QFxListViewPrivate::updateAverage()
+{
+ if (!visibleItems.count())
+ return;
+ qreal sum = 0.0;
+ for (int i = 0; i < visibleItems.count(); ++i)
+ sum += visibleItems.at(i)->size();
+ averageSize = sum / visibleItems.count();
+}
+
+void QFxListViewPrivate::fixupPosition()
+{
+ if (orient == Qt::Vertical)
+ fixupY();
+ else
+ fixupX();
+}
+
+void QFxListViewPrivate::fixupY()
+{
+ Q_Q(QFxListView);
+ QFxFlickablePrivate::fixupY();
+ if (orient == Qt::Horizontal)
+ return;
+ if (currItemMode == QFxListView::SnapAuto) {
+ if (currentItem) {
+ moveReason = Mouse;
+ _tl.clear();
+ _tl.move(_moveY, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+ } else if (currItemMode == QFxListView::Snap) {
+ moveReason = Mouse;
+ int idx = snapIndex();
+ if (FxListItem *snapItem = visibleItem(idx)) {
+ int pos = snapItem->position() - snapPos;
+ if (pos > -q->maxYExtent())
+ pos = -q->maxYExtent();
+ else if (pos < -q->minYExtent())
+ pos = -q->minYExtent();
+ _tl.clear();
+ _tl.move(_moveY, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+ }
+}
+
+void QFxListViewPrivate::fixupX()
+{
+ Q_Q(QFxListView);
+ QFxFlickablePrivate::fixupX();
+ if (orient == Qt::Vertical)
+ return;
+ if (currItemMode == QFxListView::SnapAuto) {
+ moveReason = Mouse;
+ _tl.clear();
+ _tl.move(_moveX, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ } else if (currItemMode == QFxListView::Snap) {
+ moveReason = Mouse;
+ int idx = snapIndex();
+ if (FxListItem *snapItem = visibleItem(idx)) {
+ int pos = snapItem->position() - snapPos;
+ if (pos > -q->maxXExtent())
+ pos = -q->maxXExtent();
+ else if (pos < -q->minXExtent())
+ pos = -q->minXExtent();
+ _tl.clear();
+ _tl.move(_moveX, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass ListView
+ \inherits Flickable
+ \brief The ListView item provides a list view of items provided by a model.
+
+ The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML.
+ The items are laid out vertically or horizontally and may be flicked to scroll.
+
+ The below example creates a very simple vertical list, using a QML model.
+ \image trivialListView.png
+
+ The user interface defines a delegate to display an item, a highlight,
+ and the ListView which uses the above.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml 3
+
+ The model is defined as a ListModel using QML:
+ \quotefile doc/src/snippets/declarative/listview/dummydata/ContactModel.qml
+
+ In this case ListModel is a handy way for us to test our UI. In practice
+ the model would be implemented in C++, or perhaps via a SQL data source.
+*/
+
+QFxListView::QFxListView(QFxItem *parent)
+ : QFxFlickable(*(new QFxListViewPrivate), parent)
+{
+ Q_D(QFxListView);
+ d->init();
+}
+
+QFxListView::~QFxListView()
+{
+ Q_D(QFxListView);
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlproperty model ListView::model
+ This property holds the model providing data for the list.
+
+ The model provides a set of data that is used to create the items
+ for the view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass, a VisualModel, or a simple list.
+
+ Models can also be created directly in QML, using a \l{ListModel}.
+*/
+QVariant QFxListView::model() const
+{
+ Q_D(const QFxListView);
+ return d->modelVariant;
+}
+
+void QFxListView::setModel(const QVariant &model)
+{
+ Q_D(QFxListView);
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QFxVisualItemModel *vim = 0;
+ if (object && (vim = qobject_cast<QFxVisualItemModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setModel(model);
+ }
+ if (d->model) {
+ if (d->currentIndex >= d->model->count() || d->currentIndex < 0)
+ setCurrentIndex(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
+ refill();
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty component ListView::delegate
+
+ The delegate provides a template describing what each item in the view should look and act like.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/listview/listview.qml 0
+*/
+QmlComponent *QFxListView::delegate() const
+{
+ Q_D(const QFxListView);
+ return d->model ? d->model->delegate() : 0;
+}
+
+void QFxListView::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QFxListView);
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setDelegate(delegate);
+ d->updateCurrent(d->currentIndex);
+ refill();
+}
+
+/*!
+ \qmlproperty int ListView::currentIndex
+ \qmlproperty Item ListView::current
+
+ \c currentIndex holds the index of the current item.
+ \c current is the current item. Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QFxListView::currentIndex() const
+{
+ Q_D(const QFxListView);
+ return d->currentIndex;
+}
+
+void QFxListView::setCurrentIndex(int index)
+{
+ Q_D(QFxListView);
+ d->moveReason = QFxListViewPrivate::Other;
+ if (d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0)
+ d->updateCurrent(index);
+ else
+ d->currentIndex = index;
+}
+
+QFxItem *QFxListView::currentItem()
+{
+ Q_D(QFxListView);
+ if (!d->currentItem) {
+ // Always return something valid
+ if (!d->tmpCurrent) {
+ d->tmpCurrent = new QFxItem;
+ d->tmpCurrent->setParent(viewport());
+ }
+ return d->tmpCurrent;
+ }
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty int ListView::count
+ This property holds the number of items in the view.
+*/
+int QFxListView::count() const
+{
+ Q_D(const QFxListView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty component ListView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each list.
+ The geometry of the resultant component instance will be managed by the list
+ so as to stay with the current item, unless the autoHighlight property is false.
+
+ The below example demonstrates how to make a simple highlight
+ for a vertical list.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml 1
+ \image trivialListView.png
+
+ \sa autoHighlight
+*/
+QmlComponent *QFxListView::highlight() const
+{
+ Q_D(const QFxListView);
+ return d->highlightComponent;
+}
+
+void QFxListView::setHighlight(QmlComponent *highlight)
+{
+ Q_D(QFxListView);
+ delete d->highlightComponent;
+ d->highlightComponent = highlight;
+ d->updateCurrent(d->currentIndex);
+}
+
+/*!
+ \qmlproperty bool ListView::autoHighlight
+ This property holds whether the highlight is managed by the view.
+
+ If autoHighlight is true, the highlight will be moved smoothly
+ to follow the current item. If autoHighlight is false, the
+ highlight will not be moved by the view, and must be implemented
+ by the highlight. The following example creates a highlight with
+ its motion defined by the spring \l {Follow}:
+
+ \snippet doc/src/snippets/declarative/listview/highlight.qml 1
+
+ \sa highlight
+*/
+bool QFxListView::autoHighlight() const
+{
+ Q_D(const QFxListView);
+ return d->autoHighlight;
+}
+
+void QFxListView::setAutoHighlight(bool autoHighlight)
+{
+ Q_D(QFxListView);
+ d->autoHighlight = autoHighlight;
+ if (d->highlightPosAnimator) {
+ d->highlightPosAnimator->setEnabled(d->autoHighlight);
+ d->highlightSizeAnimator->setEnabled(d->autoHighlight);
+ }
+ d->updateHighlight();
+}
+
+/*!
+ \qmlproperty enumeration ListView::currentItemPositioning
+ This property determines the current item positioning and selection characteristics.
+
+ The modes supported are:
+ \list
+ \i Free - For Mouse, the current item may be positioned anywhere,
+ whether within the visible area, or outside. During Keyboard interaction,
+ the current item can move within the visible area, and the view will
+ scroll to keep the highlight visible.
+ \i Snap - For mouse, the current item may be positioned anywhere,
+ whether within the visible area, or outside. During keyboard interaction,
+ the current item will be kept in the visible area and will prefer to be
+ positioned at the \l snapPosition, however the view will never scroll
+ beyond the beginning or end of the view.
+ \i SnapAuto - For both mouse and keyboard, the current item will be
+ kept at the \l {snapPosition}. Additionally, if the view is dragged or
+ flicked, the current item will be automatically updated to be the item
+ currently at the snapPosition.
+ \endlist
+*/
+QFxListView::CurrentItemPositioning QFxListView::currentItemPositioning() const
+{
+ Q_D(const QFxListView);
+ return d->currItemMode;
+}
+
+void QFxListView::setCurrentItemPositioning(CurrentItemPositioning mode)
+{
+ Q_D(QFxListView);
+ d->currItemMode = mode;
+}
+
+/*!
+ \qmlproperty int ListView::snapPosition
+
+ When currentItemPositioning is set to Snap or SnapAuto, the
+ \c snapPosition determines where the top of the items will
+ snap to.
+*/
+int QFxListView::snapPosition() const
+{
+ Q_D(const QFxListView);
+ return d->snapPos;
+}
+
+void QFxListView::setSnapPosition(int pos)
+{
+ Q_D(QFxListView);
+ d->snapPos = pos;
+}
+
+/*!
+ \qmlproperty enumeration ListView::orientation
+ This property holds the orientation of the list.
+
+ Possible values are \c Vertical (default) and \c Horizontal.
+
+ Vertical Example:
+ \image trivialListView.png
+ Horizontal Example:
+ \image ListViewHorizontal.png
+*/
+Qt::Orientation QFxListView::orientation() const
+{
+ Q_D(const QFxListView);
+ return d->orient;
+}
+
+void QFxListView::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QFxListView);
+ if (d->orient != orientation) {
+ d->orient = orientation;
+ if (d->orient == Qt::Vertical)
+ setViewportWidth(-1);
+ else
+ setViewportHeight(-1);
+ d->clear();
+ refill();
+ d->updateCurrent(d->currentIndex);
+ }
+}
+
+/*!
+ \qmlproperty bool ListView::wrap
+ This property holds whether the list wraps key navigation
+
+ If this property is true then key presses to move off of one end of the list will cause the
+ selection to jump to the other side.
+*/
+bool QFxListView::isWrapEnabled() const
+{
+ Q_D(const QFxListView);
+ return d->wrap;
+}
+
+void QFxListView::setWrapEnabled(bool wrap)
+{
+ Q_D(QFxListView);
+ d->wrap = wrap;
+}
+
+/*!
+ \qmlproperty int ListView::cacheBuffer
+ This property holds the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the list
+ and below the bottom of the list to cache. Setting this value can make
+ scrolling the list smoother at the expense of additional memory usage.
+*/
+
+/*!
+ \property QFxListView::cacheBuffer
+ \brief sets the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the list
+ and below the bottom of the list to cache. Setting this value can make
+ scrolling the list smoother at the expense of additional memory usage.
+*/
+int QFxListView::cacheBuffer() const
+{
+ Q_D(const QFxListView);
+ return d->buffer;
+}
+
+void QFxListView::setCacheBuffer(int b)
+{
+ Q_D(QFxListView);
+ if (d->buffer != b) {
+ d->buffer = b;
+ if (isComponentComplete())
+ refill();
+ }
+}
+
+/*!
+ \qmlproperty string ListView::sectionExpression
+ This property holds the expression to be evaluated for the section attached property.
+
+ Each item in the list has attached properties named \c ListView.section and
+ \c ListView.prevSection. These may be used to place a section header for
+ related items. The example below assumes that the model is sorted by size of
+ pet. The section expression is the size property. If \c ListView.section and
+ \c ListView.prevSection differ, the item will display a section header.
+
+ \snippet examples/declarative/listview/sections.qml 0
+
+ \image ListViewSections.png
+*/
+QString QFxListView::sectionExpression() const
+{
+ Q_D(const QFxListView);
+ return d->sectionExpression;
+}
+
+void QFxListView::setSectionExpression(const QString &expression)
+{
+ Q_D(QFxListView);
+ if (d->sectionExpression != expression) {
+ d->sectionExpression = expression;
+ emit sectionExpressionChanged();
+ }
+}
+
+QString QFxListView::currentSection() const
+{
+ Q_D(const QFxListView);
+ return d->currentSection;
+}
+
+void QFxListView::viewportMoved()
+{
+ Q_D(QFxListView);
+ QFxFlickable::viewportMoved();
+ refill();
+ if (isFlicking() || d->pressed)
+ d->moveReason = QFxListViewPrivate::Mouse;
+ if (d->currItemMode == SnapAuto && d->moveReason == QFxListViewPrivate::Mouse) {
+ // Update current index
+ int idx = d->snapIndex();
+ if (idx >= 0 && idx != d->currentIndex)
+ d->updateCurrent(idx);
+ }
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::minYExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Horizontal)
+ return QFxFlickable::minYExtent();
+ qreal extent = -d->startPosition();
+ if (d->currItemMode == SnapAuto)
+ extent += d->snapPos;
+
+ return extent;
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::maxYExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Horizontal)
+ return QFxFlickable::maxYExtent();
+ qreal extent;
+ if (d->currItemMode == SnapAuto)
+ extent = -(d->positionAt(count()-1) - d->snapPos);
+ else
+ extent = -(d->endPosition() - height());
+ if (extent > 0)
+ extent = 0;
+ return extent;
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::minXExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Vertical)
+ return QFxFlickable::minXExtent();
+ qreal extent = -d->startPosition();
+ if (d->currItemMode == SnapAuto)
+ extent += d->snapPos;
+
+ return extent;
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::maxXExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Vertical)
+ return QFxFlickable::maxXExtent();
+ qreal extent;
+ if (d->currItemMode == SnapAuto)
+ extent = -(d->positionAt(count()-1) - d->snapPos);
+ else
+ extent = -(d->endPosition() - width());
+ if (extent > 0)
+ extent = 0;
+ return extent;
+}
+
+void QFxListView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QFxListView);
+ if (d->model && d->model->count() && !d->locked) {
+ if ((d->orient == Qt::Horizontal && event->key() == Qt::Key_Left)
+ || (d->orient == Qt::Vertical && event->key() == Qt::Key_Up)) {
+ if (currentIndex() > 0 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxListViewPrivate::Key;
+ int index = currentIndex()-1;
+ d->updateCurrent(index >= 0 ? index : d->model->count()-1);
+ event->accept();
+ }
+ return;
+ } else if ((d->orient == Qt::Horizontal && event->key() == Qt::Key_Right)
+ || (d->orient == Qt::Vertical && event->key() == Qt::Key_Down)) {
+ if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxListViewPrivate::Key;
+ int index = currentIndex()+1;
+ d->updateCurrent(index < d->model->count() ? index : 0);
+ event->accept();
+ }
+ return;
+ }
+ }
+ d->moveReason = QFxListViewPrivate::Other;
+ QFxFlickable::keyPressEvent(event);
+}
+
+void QFxListView::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QFxListView);
+ d->keyPressed = false;
+ QFxFlickable::keyReleaseEvent(event);
+}
+
+void QFxListView::componentComplete()
+{
+ Q_D(QFxListView);
+ QFxFlickable::componentComplete();
+ if (d->currentIndex < 0)
+ d->updateCurrent(0);
+ refill();
+ d->fixupPosition();
+}
+
+void QFxListView::refill()
+{
+ Q_D(QFxListView);
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+void QFxListView::trackedPositionChanged()
+{
+ Q_D(QFxListView);
+ if (!d->trackedItem)
+ return;
+ if (!isFlicking() && !d->pressed && d->moveReason != QFxListViewPrivate::Mouse) {
+ switch (d->currItemMode) {
+ case Free:
+ if (d->trackedItem->position() < d->position()) {
+ d->setPosition(d->trackedItem->position());
+ } else if (d->trackedItem->endPosition() > d->position() + d->size()) {
+ qreal pos = d->trackedItem->endPosition() - d->size();
+ if (d->trackedItem->size() > d->size())
+ pos = d->trackedItem->position();
+ d->setPosition(pos);
+ }
+ d->fixupPosition();
+ break;
+ case Snap:
+ if (d->trackedItem->position() < d->startPosition() + d->snapPos)
+ d->setPosition(d->startPosition());
+ else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + d->snapPos + d->trackedItem->size())
+ d->setPosition(d->endPosition() - d->size());
+ else
+ d->setPosition(d->trackedItem->position() - d->snapPos);
+ break;
+ case SnapAuto:
+ d->setPosition(d->trackedItem->position() - d->snapPos);
+ break;
+ }
+ } else if (d->fixCurrentVisibility && d->currentItem && !d->pressed) {
+ /*
+ if (d->trackedItem->position() < d->position()
+ && d->currentItem->position() < d->position()) {
+ d->setPosition(d->trackedItem->position());
+ } else if (d->size() && d->trackedItem->size() <= d->size()
+ && d->trackedItem->endPosition() > d->position() + d->size()
+ && d->currentItem->endPosition() > d->position() + d->size()) {
+ d->setPosition(d->trackedItem->endPosition() - d->size());
+ }
+ if (d->trackedItem->position() == d->currentItem->position())
+ d->fixCurrentVisibility = false;
+ */
+ }
+}
+
+void QFxListView::itemResized()
+{
+ Q_D(QFxListView);
+ QFxItem *item = qobject_cast<QFxItem*>(sender());
+ if (item) {
+ d->activeItem = item; // Ick - don't delete the sender
+ d->layout();
+ d->activeItem = 0;
+ d->fixupPosition();
+ }
+}
+
+void QFxListView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QFxListView);
+ d->updateUnrequestedIndexes();
+ if (!d->visibleItems.count() || d->model->count() <= 1) {
+ d->layout();
+ d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
+ emit countChanged();
+ return;
+ }
+
+ if (!d->mapRangeFromModel(modelIndex, count)) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ // Special case of appending an item to the model.
+ modelIndex = d->visibleIndex + d->visibleItems.count();
+ } else {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxListItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+ }
+
+ // At least some of the added items will be visible
+
+ int index = modelIndex - d->visibleIndex;
+ int to = d->buffer+d->position()+d->size()-1;
+ // index can be the next item past the end of the visible items list (i.e. appended)
+ int pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
+ : d->visibleItems.at(index-1)->endPosition()+1;
+ int initialPos = pos;
+ QList<FxListItem*> added;
+ for (int i = 0; i < count && pos <= to; ++i) {
+ FxListItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(pos);
+ added.append(item);
+ pos += item->size();
+ ++index;
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->currentItem->position() + (pos - initialPos));
+ }
+ }
+ if (pos > to) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index)
+ d->releaseItem(d->visibleItems.takeLast());
+ } else {
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxListItem *listItem = d->visibleItems.at(index);
+ listItem->setPosition(listItem->position() + (pos - initialPos));
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ }
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+ d->updateUnrequestedPositions();
+ emit countChanged();
+}
+
+void QFxListView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QFxListView);
+ d->updateUnrequestedIndexes();
+ if (!d->mapRangeFromModel(modelIndex, count)) {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Items removed before our visible items.
+ d->visibleIndex -= count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxListItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1)
+ listItem->index -= count;
+ }
+ }
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxListItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (d->visibleItems.isEmpty()) {
+ d->visibleIndex = 0;
+ d->visiblePos = 0;
+ d->_tl.clear();
+ d->setPosition(0);
+ if (d->model->count() == 0)
+ update();
+ else
+ refill();
+ } else {
+ // Correct the positioning of the items
+ d->layout();
+ }
+
+ emit countChanged();
+}
+
+void QFxListView::destroyRemoved()
+{
+ Q_D(QFxListView);
+ for (QList<FxListItem*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxListItem *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->layout();
+}
+
+void QFxListView::createdItem(int index, QFxItem *item)
+{
+ Q_D(QFxListView);
+ if (d->requestedIndex != index) {
+ item->setItemParent(viewport());
+ d->unrequestedItems.insert(item, index);
+ if (d->orient == Qt::Vertical)
+ item->setY(d->positionAt(index));
+ else
+ item->setX(d->positionAt(index));
+ }
+}
+
+void QFxListView::destroyingItem(QFxItem *item)
+{
+ Q_D(QFxListView);
+ d->unrequestedItems.remove(item);
+}
+
+QObject *QFxListView::qmlAttachedProperties(QObject *obj)
+{
+ return QFxListViewAttached::properties(obj);
+}
+
+QML_DEFINE_TYPE(QFxListView,ListView)
+
+QT_END_NAMESPACE
+#include "qfxlistview.moc"
diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h
new file mode 100644
index 0000000..5dfb0e4
--- /dev/null
+++ b/src/declarative/fx/qfxlistview.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXLISTVIEW_H
+#define QFXLISTVIEW_H
+
+#include <QtDeclarative/qfxflickable.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxVisualItemModel;
+class QFxListViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFxListView)
+
+ Q_ENUMS(CurrentItemPositioning)
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QFxItem *current READ currentItem NOTIFY currentIndexChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight)
+ Q_PROPERTY(bool autoHighlight READ autoHighlight WRITE setAutoHighlight)
+ Q_PROPERTY(CurrentItemPositioning currentItemPositioning READ currentItemPositioning WRITE setCurrentItemPositioning)
+ Q_PROPERTY(int snapPosition READ snapPosition WRITE setSnapPosition)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_PROPERTY(bool wrap READ isWrapEnabled WRITE setWrapEnabled)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer)
+ Q_PROPERTY(QString sectionExpression READ sectionExpression WRITE setSectionExpression NOTIFY sectionExpressionChanged)
+ Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
+
+public:
+ QFxListView(QFxItem *parent=0);
+ ~QFxListView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QFxItem *currentItem();
+ int count() const;
+
+ QmlComponent *highlight() const;
+ void setHighlight(QmlComponent *highlight);
+
+ bool autoHighlight() const;
+ void setAutoHighlight(bool);
+
+ enum CurrentItemPositioning { Free, Snap, SnapAuto };
+ CurrentItemPositioning currentItemPositioning() const;
+ void setCurrentItemPositioning(CurrentItemPositioning mode);
+
+ int snapPosition() const;
+ void setSnapPosition(int pos);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation);
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ QString sectionExpression() const;
+ void setSectionExpression(const QString &);
+ QString currentSection() const;
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void countChanged();
+ void currentIndexChanged();
+ void currentSectionChanged();
+ void sectionExpressionChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void refill();
+ void trackedPositionChanged();
+ void itemResized();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void destroyRemoved();
+ void createdItem(int index, QFxItem *item);
+ void destroyingItem(QFxItem *item);
+};
+
+QML_DECLARE_TYPE(QFxListView)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/fx/qfxmouseregion.cpp b/src/declarative/fx/qfxmouseregion.cpp
new file mode 100644
index 0000000..6eb358b
--- /dev/null
+++ b/src/declarative/fx/qfxmouseregion.cpp
@@ -0,0 +1,580 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxmouseregion.h"
+#include "qfxmouseregion_p.h"
+#include "qfxevents_p.h"
+#include <QGraphicsSceneMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+static const int DragThreshold = 5;
+static const int PressAndHoldDelay = 800;
+
+QML_DEFINE_TYPE(QFxDrag,Drag)
+QFxDrag::QFxDrag(QObject *parent)
+: QObject(parent), _target(0), _xmin(0), _xmax(0), _ymin(0), _ymax(0)
+{
+}
+
+QFxDrag::~QFxDrag()
+{
+}
+
+QFxItem *QFxDrag::target() const
+{
+ return _target;
+}
+
+void QFxDrag::setTarget(QFxItem *t)
+{
+ _target = t;
+}
+
+QString QFxDrag::axis() const
+{
+ return _axis;
+}
+
+void QFxDrag::setAxis(const QString &a)
+{
+ _axis = a;
+}
+
+/*!
+ \property QFxDrag::xmin
+ \brief the minimum x position for the target
+
+ If x-axis dragging is enabled, xmin limits how far to the left the target can be dragged. If x-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::xmin() const
+{
+ return _xmin;
+}
+
+void QFxDrag::setXmin(int m)
+{
+ _xmin = m;
+}
+
+/*!
+ \property QFxDrag::xmax
+ \brief the maximum x position for the target
+
+ If x-axis dragging is enabled, xmax limits how far to the right the target can be dragged. If x-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::xmax() const
+{
+ return _xmax;
+}
+
+void QFxDrag::setXmax(int m)
+{
+ _xmax = m;
+}
+
+/*!
+ \property QFxDrag::ymin
+ \brief the minimum y position for the target
+
+ If y-axis dragging is enabled, ymin limits how far up the target can be dragged. If y-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::ymin() const
+{
+ return _ymin;
+}
+
+void QFxDrag::setYmin(int m)
+{
+ _ymin = m;
+}
+
+/*!
+ \property QFxDrag::ymax
+ \brief the maximum y position for the target
+
+ If y-axis dragging is enabled, ymax limits how far down the target can be dragged. If y-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::ymax() const
+{
+ return _ymax;
+}
+
+void QFxDrag::setYmax(int m)
+{
+ _ymax = m;
+}
+
+/*!
+ \qmlclass MouseRegion
+ \brief The MouseRegion item enables simple mouse handling.
+ \inherits Item
+
+ A MouseRegion is typically used in conjunction with a visible item,
+ where the MouseRegion effectively 'proxies' mouse handling for that
+ item. For example, we can put a MouseRegion in a Rect that changes
+ the Rect color to red when clicked:
+ \snippet doc/src/snippets/declarative/mouseregion.qml 0
+
+ Many MouseRegion signals pass a \l {MouseEvent}{mouse} parameter that contains
+ additional information about the mouse event, such as the position, button,
+ and any key modifiers.
+
+ Below we have the previous
+ example extended so as to give a different color when you right click.
+ \snippet doc/src/snippets/declarative/mouseregion.qml 1
+
+ For basic key handling, see \l KeyActions.
+
+ MouseRegion is an invisible item: it is never painted.
+
+ \sa MouseEvent
+*/
+
+/*!
+ \qmlsignal MouseRegion::onEntered
+
+ This handler is called when the mouse enters the mouse region.
+
+ \warning This handler is not yet implemented.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onExited
+
+ This handler is called when the mouse exists the mouse region.
+
+ \warning This handler is not yet implemented.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onReenteredWhilePressed
+
+ This handler is called when the mouse reenters the mouse region while pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onExitedWhilePressed
+
+ This handler is called when the mouse exists the mouse region while pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPositionChanged(mouse)
+
+ This handler is called when the mouse position changes.
+
+ The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
+ position, and any buttons currently pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onClicked(mouse)
+
+ This handler is called when there is a click. A click is defined as a press followed by a release,
+ both inside the MouseRegion (pressing, moving outside the MouseRegion, and then moving back inside and
+ releasing is also considered a click).
+
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPressed(mouse)
+
+ This handler is called when there is a press.
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position and which button was pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onReleased(mouse)
+
+ This handler is called when there is a release.
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPressAndHold(mouse)
+
+ This handler is called when there is a long press (currently 800ms).
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position of the press, and which button is pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onDoubleClicked(mouse)
+
+ This handler is called when there is a double-click (a press followed by a release followed by a press).
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+*/
+
+QML_DEFINE_TYPE(QFxMouseRegion,MouseRegion)
+
+/*!
+ \internal
+ \class QFxMouseRegion
+ \brief The QFxMouseRegion class provides a simple mouse handling abstraction for use within Qml.
+
+ \ingroup group_coreitems
+
+ All QFxItem derived classes can do mouse handling but the QFxMouseRegion class exposes mouse
+ handling data as properties and tracks flicking and dragging of the mouse.
+
+ A QFxMouseRegion object can be instantiated in Qml using the tag \l MouseRegion.
+ */
+QFxMouseRegion::QFxMouseRegion(QFxItem *parent)
+ : QFxItem(*(new QFxMouseRegionPrivate), parent)
+{
+ Q_D(QFxMouseRegion);
+ d->init();
+}
+
+QFxMouseRegion::QFxMouseRegion(QFxMouseRegionPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxMouseRegion);
+ d->init();
+}
+
+QFxMouseRegion::~QFxMouseRegion()
+{
+}
+
+/*!
+ \qmlproperty int MouseRegion::mouseX
+ \qmlproperty int MouseRegion::mouseY
+
+ The coordinates of the mouse while pressed. The coordinates are relative to the item that was pressed.
+*/
+int QFxMouseRegion::mouseX() const
+{
+ Q_D(const QFxMouseRegion);
+ return int(d->lastPos.x());
+}
+
+int QFxMouseRegion::mouseY() const
+{
+ Q_D(const QFxMouseRegion);
+ return int(d->lastPos.y());
+}
+
+/*!
+ \qmlproperty bool MouseRegion::enabled
+ This property holds whether the item accepts mouse events.
+*/
+bool QFxMouseRegion::isEnabled() const
+{
+ Q_D(const QFxMouseRegion);
+ return d->absorb;
+}
+
+void QFxMouseRegion::setEnabled(bool a)
+{
+ Q_D(QFxMouseRegion);
+ d->absorb = a;
+}
+
+void QFxMouseRegion::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ d->moved = false;
+ if (!d->absorb)
+ QFxItem::mousePressEvent(event);
+ else {
+ if (!d->inside) {
+ d->inside = true;
+ emit hoveredChanged();
+ }
+ d->longPress = false;
+ d->saveEvent(event);
+ d->dragX = drag()->axis().contains(QLatin1String("x"));
+ d->dragY = drag()->axis().contains(QLatin1String("y"));
+ d->dragged = false;
+ d->start = event->pos();
+ d->startScene = event->scenePos();
+ // ### we should only start timer if pressAndHold is connected to (but connectNotify doesn't work)
+ d->pressAndHoldTimer.start(PressAndHoldDelay, this);
+ setKeepMouseGrab(false);
+ setPressed(true);
+ event->accept();
+ }
+}
+
+void QFxMouseRegion::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb) {
+ QFxItem::mouseMoveEvent(event);
+ return;
+ }
+
+ d->saveEvent(event);
+
+ // ### we should skip this if these signals aren't used
+ const QRect &bounds = itemBoundingRect();
+ bool contains = bounds.contains(d->lastPos.toPoint());
+ if (d->inside && !contains) {
+ d->inside = false;
+ emit hoveredChanged();
+ emit exitedWhilePressed();
+ } else if (!d->inside && contains) {
+ d->inside = true;
+ emit hoveredChanged();
+ emit reenteredWhilePressed();
+ }
+
+ if (drag()->target()) {
+ if (!d->moved) {
+ if (d->dragX) d->startX = int(drag()->target()->x()); //### change startX and startY to qreal?
+ if (d->dragY) d->startY = int(drag()->target()->y());
+ }
+
+ QPointF startLocalPos;
+ QPointF curLocalPos;
+ if (drag()->target()->parent()) {
+ startLocalPos = drag()->target()->parent()->mapFromScene(d->startScene);
+ curLocalPos = drag()->target()->parent()->mapFromScene(event->scenePos());
+ } else {
+ startLocalPos = d->startScene;
+ curLocalPos = event->scenePos();
+ }
+
+ int dx = int(qAbs(curLocalPos.x() - startLocalPos.x()));
+ int dy = int(qAbs(curLocalPos.y() - startLocalPos.y()));
+ if ((d->dragX && !(dx < DragThreshold)) || (d->dragY && !(dy < DragThreshold)))
+ d->dragged = true;
+ if (!keepMouseGrab()) {
+ if ((!d->dragY && dy < DragThreshold && d->dragX && dx > DragThreshold)
+ || (!d->dragX && dx < DragThreshold && d->dragY && dy > DragThreshold)
+ || (d->dragX && d->dragY)) {
+ setKeepMouseGrab(true);
+ }
+ }
+
+ if (d->dragX) {
+ qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX;
+ if (x < drag()->xmin())
+ x = drag()->xmin();
+ else if (x > drag()->xmax())
+ x = drag()->xmax();
+ drag()->target()->setX(x);
+ }
+ if (d->dragY) {
+ qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY;
+ if (y < drag()->ymin())
+ y = drag()->ymin();
+ else if (y > drag()->ymax())
+ y = drag()->ymax();
+ drag()->target()->setY(y);
+ }
+ }
+ d->moved = true;
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit positionChanged(&me);
+ event->accept();
+}
+
+
+void QFxMouseRegion::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::mouseReleaseEvent(event);
+ else {
+ d->saveEvent(event);
+ setPressed(false);
+ //d->inside = false;
+ //emit hoveredChanged();
+ event->accept();
+ }
+}
+
+void QFxMouseRegion::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::mouseDoubleClickEvent(event);
+ else {
+ //d->inside = true;
+ //emit hoveredChanged();
+ d->saveEvent(event);
+ setPressed(true);
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
+ emit this->doubleClicked(&me);
+ event->accept();
+ }
+}
+
+void QFxMouseRegion::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::hoverEnterEvent(event);
+ else {
+ setHovered(true);
+ emit entered();
+ }
+}
+
+void QFxMouseRegion::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::hoverLeaveEvent(event);
+ else {
+ setHovered(false);
+ emit exited();
+ }
+}
+
+void QFxMouseRegion::mouseUngrabEvent()
+{
+ Q_D(QFxMouseRegion);
+ if (d->pressed) {
+ // if our mouse grab has been removed (probably by Flickable), fix our
+ // state
+ d->pressed = false;
+ //d->inside = false;
+ setKeepMouseGrab(false);
+ emit pressedChanged();
+ //emit hoveredChanged();
+ }
+}
+
+void QFxMouseRegion::timerEvent(QTimerEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (event->timerId() == d->pressAndHoldTimer.timerId()) {
+ d->pressAndHoldTimer.stop();
+ if (d->pressed && d->dragged == false && d->inside == true) {
+ d->longPress = true;
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit pressAndHold(&me);
+ }
+ }
+}
+
+/*!
+ \qmlproperty bool MouseRegion::containsMouse
+ This property holds whether the mouse is currently inside the mouse region.
+
+ \warning This property is only partially implemented -- it is only valid when the mouse is pressed, and not for hover events.
+*/
+bool QFxMouseRegion::hovered()
+{
+ Q_D(QFxMouseRegion);
+ return d->hovered || d->inside;
+}
+
+/*!
+ \qmlproperty bool MouseRegion::pressed
+ This property holds whether the mouse region is currently pressed.
+*/
+bool QFxMouseRegion::pressed()
+{
+ Q_D(QFxMouseRegion);
+ return d->pressed;
+}
+
+void QFxMouseRegion::setHovered(bool h)
+{
+ Q_D(QFxMouseRegion);
+ if (d->hovered != h) {
+ d->hovered = h;
+ emit hoveredChanged();
+ }
+}
+
+void QFxMouseRegion::setPressed(bool p)
+{
+ Q_D(QFxMouseRegion);
+ bool isclick = d->pressed == true && p == false && d->dragged == false && d->inside == true;
+
+ if (d->pressed != p) {
+ d->pressed = p;
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
+ if (d->pressed) {
+ emit positionChanged(&me);
+ emit pressed(&me);
+ } else {
+ emit released(&me);
+ if (isclick)
+ emit clicked(&me);
+ }
+
+ emit pressedChanged();
+ }
+}
+
+/*!
+ \property QFxMouseRegion::drag
+ \brief The current drag being performed on the Mouse Region.
+*/
+QFxDrag *QFxMouseRegion::drag()
+{
+ Q_D(QFxMouseRegion);
+ return &(d->drag);
+}
+
+/*!
+ \qmlproperty Item MouseRegion::drag.target
+ \qmlproperty string MouseRegion::drag.axis
+ \qmlproperty int MouseRegion::drag.xmin
+ \qmlproperty int MouseRegion::drag.xmax
+ \qmlproperty int MouseRegion::drag.ymin
+ \qmlproperty int MouseRegion::drag.ymax
+
+ drag provides a convenient way to make an item draggable.
+
+ \list
+ \i \c target specifies the item to drag.
+ \i \c axis specifies whether dragging can be done horizontally (x), vertically (y), or both (x,y)
+ \i the min and max properties limit how far the target can be dragged along the corresponding axes.
+ \endlist
+
+ The following example uses drag to reduce the opacity of an image as it moves to the right:
+ \snippet doc/src/snippets/declarative/drag.qml 0
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxmouseregion.h b/src/declarative/fx/qfxmouseregion.h
new file mode 100644
index 0000000..d7db1dc
--- /dev/null
+++ b/src/declarative/fx/qfxmouseregion.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXMOUSEREGION_H
+#define QFXMOUSEREGION_H
+
+#include <QtDeclarative/qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QFxDrag : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxItem *target READ target WRITE setTarget)
+ Q_PROPERTY(QString axis READ axis WRITE setAxis)
+ Q_PROPERTY(int xmin READ xmin WRITE setXmin)
+ Q_PROPERTY(int xmax READ xmax WRITE setXmax)
+ Q_PROPERTY(int ymin READ ymin WRITE setYmin)
+ Q_PROPERTY(int ymax READ ymax WRITE setYmax)
+public:
+ QFxDrag(QObject *parent=0);
+ ~QFxDrag();
+
+ QFxItem *target() const;
+ void setTarget(QFxItem *);
+ QString axis() const;
+ void setAxis(const QString &);
+ int xmin() const;
+ void setXmin(int);
+ int xmax() const;
+ void setXmax(int);
+ int ymin() const;
+ void setYmin(int);
+ int ymax() const;
+ void setYmax(int);
+
+private:
+ QFxItem *_target;
+ QString _axis;
+ int _xmin;
+ int _xmax;
+ int _ymin;
+ int _ymax;
+ Q_DISABLE_COPY(QFxDrag)
+};
+QML_DECLARE_TYPE(QFxDrag)
+
+class QFxMouseEvent;
+class QFxMouseRegionPrivate;
+class Q_DECLARATIVE_EXPORT QFxMouseRegion : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int mouseX READ mouseX NOTIFY positionChanged)
+ Q_PROPERTY(int mouseY READ mouseY NOTIFY positionChanged)
+ Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged)
+ Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(QFxDrag *drag READ drag)
+public:
+ QFxMouseRegion(QFxItem *parent=0);
+ ~QFxMouseRegion();
+
+ int mouseX() const;
+ int mouseY() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ bool hovered();
+ bool pressed();
+
+ void setHovered(bool);
+ void setPressed(bool);
+
+ QFxDrag *drag();
+
+Q_SIGNALS:
+ void hoveredChanged();
+ void pressedChanged();
+ void positionChanged(QFxMouseEvent *mouse);
+
+ void pressed(QFxMouseEvent *mouse);
+ void pressAndHold(QFxMouseEvent *mouse);
+ void released(QFxMouseEvent *mouse);
+ void clicked(QFxMouseEvent *mouse);
+ void doubleClicked(QFxMouseEvent *mouse);
+ void entered();
+ void exited();
+ void exitedWhilePressed();
+ void reenteredWhilePressed();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+ void mouseUngrabEvent();
+ void timerEvent(QTimerEvent *event);
+
+private:
+ void handlePress();
+ void handleRelease();
+
+protected:
+ QFxMouseRegion(QFxMouseRegionPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxMouseRegion)
+ Q_DECLARE_PRIVATE(QFxMouseRegion)
+};
+QML_DECLARE_TYPE(QFxMouseRegion)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXMOUSEREGION_H
diff --git a/src/declarative/fx/qfxmouseregion_p.h b/src/declarative/fx/qfxmouseregion_p.h
new file mode 100644
index 0000000..e444bf2
--- /dev/null
+++ b/src/declarative/fx/qfxmouseregion_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXMOUSEREGION_P_H
+#define QFXMOUSEREGION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qdatetime.h"
+#include "qbasictimer.h"
+#include "qgraphicssceneevent.h"
+#include "qfxitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QFxMouseRegionPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxMouseRegion)
+
+public:
+ QFxMouseRegionPrivate()
+ : absorb(true), hovered(false), inside(true), pressed(false), longPress(false), drag(0)
+ {
+ }
+
+ void init()
+ {
+ Q_Q(QFxMouseRegion);
+ q->setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
+ q->setOptions(QSimpleCanvasItem::HoverEvents | QSimpleCanvasItem::MouseEvents);
+ }
+
+ void saveEvent(QGraphicsSceneMouseEvent *event) {
+ lastPos = event->pos();
+ lastButton = event->button();
+ lastButtons = event->buttons();
+ lastModifiers = event->modifiers();
+ }
+
+ bool absorb : 1;
+ bool hovered : 1;
+ bool inside : 1;
+ bool pressed : 1;
+ bool longPress : 1;
+ bool moved : 1;
+ bool dragX : 1;
+ bool dragY : 1;
+ bool dragged : 1;
+ QFxDrag drag;
+ QPointF start;
+ QPointF startScene;
+ int startX;
+ int startY;
+ QPointF lastPos;
+ Qt::MouseButton lastButton;
+ Qt::MouseButtons lastButtons;
+ Qt::KeyboardModifiers lastModifiers;
+ QBasicTimer pressAndHoldTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXMOUSEREGION_P_H
diff --git a/src/declarative/fx/qfxpainteditem.cpp b/src/declarative/fx/qfxpainteditem.cpp
new file mode 100644
index 0000000..44adba7
--- /dev/null
+++ b/src/declarative/fx/qfxpainteditem.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxpainteditem.h"
+#include "qfxpainteditem_p.h"
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glsave.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QFxPaintedItem
+ \brief The QFxPaintedItem class is an abstract base class for QFxView items that want cached painting.
+ \ingroup group_coreitems
+
+ This is a convenience class for implementing items that paint their contents
+ using a QPainter. The contents of the item are are cached behind the scenes.
+ The dirtyCache() function should be called if the contents change to
+ ensure the cache is refreshed the next time painting occurs.
+
+ To subclass QFxPaintedItem, you must reimplement drawContents() to draw
+ the contents of the item.
+*/
+
+/*!
+ \fn void QFxPaintedItem::drawContents(QPainter *painter, const QRect &rect)
+
+ This function is called when the cache needs to be refreshed. When
+ sub-classing QFxPaintedItem this function should be implemented so as to
+ paint the contents of the item using the given \a painter for the
+ area of the contents specified by \a rect.
+*/
+
+/*!
+ \property QFxPaintedItem::contentsSize
+ \brief The size of the contents
+
+ The contents size is the size of the item in regards to how it is painted
+ using the drawContents() function. This is distinct from the size of the
+ item in regards to height() and width().
+*/
+
+/*!
+ \property QFxPaintedItem::smooth
+ \brief Setting for whether smooth scaling is enabled.
+*/
+
+/*!
+ Marks areas of the cache that intersect with the given \a rect as dirty and
+ in need of being refreshed.
+
+ \sa clearCache()
+*/
+void QFxPaintedItem::dirtyCache(const QRect& rect)
+{
+ Q_D(QFxPaintedItem);
+ for (int i=0; i < d->imagecache.count(); ) {
+ if (d->imagecache[i]->area.intersects(rect)) {
+ d->imagecache.removeAt(i);
+ } else {
+ ++i;
+ }
+ }
+}
+
+/*!
+ Marks the entirety of the contents cache as dirty.
+
+ \sa dirtyCache()
+*/
+void QFxPaintedItem::clearCache()
+{
+ Q_D(QFxPaintedItem);
+ qDeleteAll(d->imagecache);
+ d->imagecache.clear();
+}
+
+/*!
+ Returns if smooth scaling of the cache contents is enabled.
+
+ \sa setSmooth()
+*/
+bool QFxPaintedItem::isSmooth() const
+{
+ Q_D(const QFxPaintedItem);
+ return d->smooth;
+}
+
+/*!
+ Returns the size of the contents.
+
+ \sa setContentsSize()
+*/
+QSize QFxPaintedItem::contentsSize() const
+{
+ Q_D(const QFxPaintedItem);
+ return d->contentsSize;
+}
+
+/*!
+ If \a smooth is true sets the image item to enable smooth scaling of
+ the cache contents.
+
+ \sa isSmooth()
+*/
+void QFxPaintedItem::setSmooth(bool smooth)
+{
+ Q_D(QFxPaintedItem);
+ if (d->smooth == smooth) return;
+ d->smooth = smooth;
+ clearCache();
+ update();
+}
+
+/*!
+ Sets the size of the contents to the given \a size.
+
+ \sa contentsSize()
+*/
+void QFxPaintedItem::setContentsSize(const QSize &size)
+{
+ Q_D(QFxPaintedItem);
+ if (d->contentsSize == size) return;
+ d->contentsSize = size;
+ clearCache();
+ update();
+}
+
+/*!
+ Constructs a new QFxPaintedItem with the given \a parent.
+*/
+QFxPaintedItem::QFxPaintedItem(QFxItem *parent)
+ : QFxItem(*(new QFxPaintedItemPrivate), parent)
+{
+ init();
+}
+
+/*!
+ \internal
+ Constructs a new QFxPaintedItem with the given \a parent and
+ initialized private data member \a dd.
+*/
+QFxPaintedItem::QFxPaintedItem(QFxPaintedItemPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ init();
+}
+
+/*!
+ Destroys the image item.
+*/
+QFxPaintedItem::~QFxPaintedItem()
+{
+}
+
+/*!
+ \internal
+*/
+void QFxPaintedItem::init()
+{
+ connect(this,SIGNAL(widthChanged()),this,SLOT(clearCache()));
+ connect(this,SIGNAL(heightChanged()),this,SLOT(clearCache()));
+ connect(this,SIGNAL(visibleChanged()),this,SLOT(clearCache()));
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+/*!
+ \reimp
+*/
+void QFxPaintedItem::paintContents(QPainter &p)
+#elif defined(QFX_RENDER_OPENGL)
+/*!
+ \reimp
+*/
+void QFxPaintedItem::paintGLContents(GLPainter &p)
+#else
+#error "What render?"
+#endif
+{
+ Q_D(QFxPaintedItem);
+ const QRect content(QPoint(0,0),d->contentsSize);
+ if (content.width() <= 0 || content.height() <= 0)
+ return;
+
+#if defined(QFX_RENDER_QPAINTER)
+ bool oldAntiAliasing = p.testRenderHint(QPainter::Antialiasing);
+ bool oldSmoothPixmap = p.testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth) {
+ p.setRenderHints(QPainter::Antialiasing, true);
+ p.setRenderHints(QPainter::SmoothPixmapTransform, true);
+ }
+ QRectF clipf = p.clipRegion().boundingRect();
+ if (clipf.isEmpty())
+ clipf = mapToScene(content); // ### Inefficient: Maps toScene and then fromScene
+ else
+ clipf = mapToScene(clipf);
+
+#elif defined(QFX_RENDER_OPENGL2)
+ p.useTextureShader();
+ const QRectF clipf = p.sceneClipRect;
+
+#elif defined(QFX_RENDER_OPENGL1)
+ p.useTextureShader();
+ const QRectF clipf = p.sceneClipRect;
+#endif
+
+ const QRect clip = mapFromScene(clipf).toRect();
+
+ QRegion topaint(clip);
+ topaint &= content;
+ QRegion uncached(content);
+
+#if defined(QFX_RENDER_OPENGL2)
+ glEnableVertexAttribArray(SingleTextureShader::Vertices);
+ glEnableVertexAttribArray(SingleTextureShader::TextureCoords);
+#elif defined(QFX_RENDER_OPENGL1)
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
+
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ if (topaint.contains(area)) {
+ QRectF target(area.x(), area.y(), area.width(), area.height());
+ p.drawPixmap(target.toRect(), d->imagecache[i]->image);
+ topaint -= area;
+ d->imagecache[i]->age=0;
+ } else {
+ d->imagecache[i]->age++;
+ }
+ cachesize += area.width()*area.height();
+ uncached -= area;
+ }
+
+ if (!topaint.isEmpty()) {
+ // Find a sensible larger area, otherwise will paint lots of tiny images.
+ QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
+ cachesize += biggerrect.width() * biggerrect.height();
+ while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ uncached += d->imagecache[oldest]->area;
+ d->imagecache.removeAt(oldest);
+ }
+ const QRegion bigger = QRegion(biggerrect) & uncached;
+ const QVector<QRect> rects = bigger.rects();
+ for (int i = 0; i < rects.count(); ++i) {
+ const QRect &r = rects.at(i);
+ QPixmap img(r.size());
+ img.fill(Qt::transparent);
+ {
+ QPainter qp(&img);
+ qp.translate(-r.x(),-r.y());
+ drawContents(&qp, r);
+ }
+ QFxPaintedItemPrivate::ImageCacheItem *newitem = new QFxPaintedItemPrivate::ImageCacheItem;
+ newitem->area = r;
+#if defined(QFX_RENDER_QPAINTER)
+ newitem->image = img;
+#else
+ newitem->image.setImage(img.toImage());
+#endif
+ d->imagecache.append(newitem);
+ QRectF target(r.x(), r.y(), r.width(), r.height());
+ p.drawPixmap(target.toRect(), newitem->image);
+ }
+ }
+#if defined(QFX_RENDER_OPENGL2)
+ glDisableVertexAttribArray(SingleTextureShader::Vertices);
+ glDisableVertexAttribArray(SingleTextureShader::TextureCoords);
+#elif defined(QFX_RENDER_OPENGL1)
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
+#if defined(QFX_RENDER_QPAINTER)
+ if (d->smooth) {
+ p.setRenderHints(QPainter::Antialiasing, oldAntiAliasing);
+ p.setRenderHints(QPainter::SmoothPixmapTransform, oldSmoothPixmap);
+ }
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpainteditem.h b/src/declarative/fx/qfxpainteditem.h
new file mode 100644
index 0000000..e086894
--- /dev/null
+++ b/src/declarative/fx/qfxpainteditem.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGEITEM_H
+#define QFXIMAGEITEM_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxPaintedItemPrivate;
+class Q_DECLARATIVE_EXPORT QFxPaintedItem : public QFxItem
+{
+ Q_OBJECT
+public:
+ QFxPaintedItem(QFxItem *parent=0);
+ ~QFxPaintedItem();
+
+ Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize)
+ Q_PROPERTY(bool smooth READ isSmooth WRITE setSmooth)
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#elif defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+#endif
+
+ bool isSmooth() const;
+ QSize contentsSize() const;
+
+ void setSmooth(bool);
+ void setContentsSize(const QSize &);
+protected:
+ QFxPaintedItem(QFxPaintedItemPrivate &dd, QFxItem *parent);
+
+ virtual void drawContents(QPainter *p, const QRect &) = 0;
+
+protected Q_SLOTS:
+ void dirtyCache(const QRect &);
+ void clearCache();
+
+private:
+ void init();
+ Q_DISABLE_COPY(QFxPaintedItem)
+ Q_DECLARE_PRIVATE(QFxPaintedItem)
+};
+QML_DECLARE_TYPE(QFxPaintedItem)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxpainteditem_p.h b/src/declarative/fx/qfxpainteditem_p.h
new file mode 100644
index 0000000..d8d1a2a
--- /dev/null
+++ b/src/declarative/fx/qfxpainteditem_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGEITEM_P_H
+#define QFXIMAGEITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qfxitem_p.h>
+#include <QtDeclarative/qsimplecanvas.h>
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFxPaintedItemPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxPaintedItem)
+
+public:
+ QFxPaintedItemPrivate()
+ : max_imagecache_size(1000*1000), smooth(false)
+ {
+ }
+
+ struct ImageCacheItem {
+ ImageCacheItem() : age(0) {}
+ ~ImageCacheItem() { }
+ int age;
+ QRect area;
+#if defined(QFX_RENDER_QPAINTER)
+ QPixmap image;
+#else
+ GLTexture image;
+#endif
+ };
+
+ QList<ImageCacheItem*> imagecache;
+
+ const int max_imagecache_size;
+ bool smooth;
+ QSize contentsSize;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxparticles.cpp b/src/declarative/fx/qfxparticles.cpp
new file mode 100644
index 0000000..41fb5bc
--- /dev/null
+++ b/src/declarative/fx/qfxparticles.cpp
@@ -0,0 +1,1200 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxitem_p.h"
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#define M_PI_2 (M_PI / 2.)
+#endif
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+#include <qfxpixmap.h>
+#include <qfxperf.h>
+#include <private/qmlanimation_p.h>
+
+#include "qfxparticles.h"
+
+
+QT_BEGIN_NAMESPACE
+#define PI_SQR 9.8696044
+// parabolic approximation
+inline qreal fastSin(qreal theta)
+{
+ const qreal b = 4 / M_PI;
+ const qreal c = -4 / PI_SQR;
+
+ qreal y = b * theta + c * theta * qAbs(theta);
+ return y;
+}
+
+inline qreal fastCos(qreal theta)
+{
+ theta += M_PI_2;
+ if (theta > M_PI)
+ theta -= 2 * M_PI;
+
+ return fastSin(theta);
+}
+
+class QFxParticle
+{
+public:
+ QFxParticle(int time) : lifeSpan(1000), fadeOutAge(800)
+ , opacity(0), birthTime(time), x_velocity(0), y_velocity(0)
+ , state(FadeIn), data(0)
+ {
+ }
+
+ int lifeSpan;
+ int fadeOutAge;
+ qreal x;
+ qreal y;
+ qreal opacity;
+ int birthTime;
+ qreal x_velocity;
+ qreal y_velocity;
+ enum State { FadeIn, Solid, FadeOut };
+ State state;
+ void *data;
+};
+
+//---------------------------------------------------------------------------
+
+QML_DEFINE_TYPE(QFxParticleMotion,ParticleMotion)
+
+/*!
+ \class QFxParticleMotion
+ \ingroup group_effects
+ \brief The QFxParticleMotion class is the base class for particle motion.
+
+ This class causes the particles to remain static.
+*/
+
+/*!
+ Constructs a QFxParticleMotion with parent object \a parent.
+*/
+QFxParticleMotion::QFxParticleMotion(QObject *parent) :
+ QObject(parent)
+{
+}
+
+/*!
+ Move the \a particle to its new position. \a interval is the number of
+ milliseconds elapsed since it was last moved.
+*/
+void QFxParticleMotion::advance(QFxParticle &particle, int interval)
+{
+ Q_UNUSED(particle);
+ Q_UNUSED(interval);
+}
+
+/*!
+ The \a particle has just been created. Some motion strategies require
+ additional state information. This can be allocated by this function.
+*/
+void QFxParticleMotion::created(QFxParticle &particle)
+{
+ Q_UNUSED(particle);
+}
+
+/*!
+ The \a particle is about to be destroyed. Any additional memory
+ that has been allocated for the particle should be freed.
+*/
+void QFxParticleMotion::destroy(QFxParticle &particle)
+{
+ Q_UNUSED(particle);
+}
+
+/*!
+ \qmlclass ParticleMotionLinear
+ \brief The ParticleMotionLinear object moves particles linearly.
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QFxParticleMotionLinear
+ \ingroup group_effects
+ \brief The QFxParticleMotionLinear class moves the particles linearly.
+*/
+
+QML_DEFINE_TYPE(QFxParticleMotionLinear,ParticleMotionLinear)
+
+void QFxParticleMotionLinear::advance(QFxParticle &p, int interval)
+{
+ p.x += interval * p.x_velocity;
+ p.y += interval * p.y_velocity;
+}
+
+/*!
+ \qmlclass ParticleMotionGravity
+ \brief The ParticleMotionGravity object moves particles towards a point.
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QFxParticleMotionGravity
+ \ingroup group_effects
+ \brief The QFxParticleMotionGravity class moves the particles towards a point.
+*/
+
+QML_DEFINE_TYPE(QFxParticleMotionGravity,ParticleMotionGravity)
+
+/*!
+ \qmlproperty int ParticleMotionGravity::xattractor
+ \qmlproperty int ParticleMotionGravity::yattractor
+ These properties hold the x and y coordinates of the point attracting the particles.
+*/
+
+/*!
+ \qmlproperty int ParticleMotionGravity::acceleration
+ This property holds the acceleration to apply to the particles.
+*/
+
+/*!
+ \property QFxParticleMotionGravity::xattractor
+ \brief the x coordinate of the point attracting the particles.
+*/
+
+/*!
+ \property QFxParticleMotionGravity::yattractor
+ \brief the y coordinate of the point attracting the particles.
+*/
+
+/*!
+ \property QFxParticleMotionGravity::acceleration
+ \brief the acceleration to apply to the particles.
+*/
+
+void QFxParticleMotionGravity::advance(QFxParticle &p, int interval)
+{
+ qreal xdiff = p.x - _xAttr;
+ qreal ydiff = p.y - _yAttr;
+
+ qreal xcomp = xdiff / (xdiff + ydiff);
+ qreal ycomp = ydiff / (xdiff + ydiff);
+
+ p.x_velocity += xcomp * _accel * interval;
+ p.y_velocity += ycomp * _accel * interval;
+
+ p.x += interval * p.x_velocity;
+ p.y += interval * p.y_velocity;
+}
+
+/*!
+ \qmlclass ParticleMotionWander
+ \brief The ParticleMotionWander object moves particles in a somewhat random fashion.
+
+ The particles will continue roughly in the original direction, however will randomly
+ drift to each side.
+
+ The code below produces an effect similar to falling snow.
+
+ \qml
+Rect {
+ width: 240
+ height: 320
+ color: "black"
+
+ Particles {
+ y: 0
+ width: parent.width
+ height: 30
+ source: "star.png"
+ lifeSpan: 5000
+ count: 50
+ angle: 70
+ angleDeviation: 36
+ velocity: 30
+ velocityDeviation: 10
+ ParticleMotionWander {
+ xvariance: 30
+ pace: 100
+ }
+ }
+}
+ \endqml
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QFxParticleMotionWander
+ \ingroup group_effects
+ \brief The QFxParticleMotionWander class moves particles in a somewhat random fashion.
+
+ The particles will continue roughly in the original direction, however will randomly
+ drift to each side.
+*/
+
+/*!
+ \qmlproperty int QFxParticleMotionWander::xvariance
+ \qmlproperty int QFxParticleMotionWander::yvariance
+
+ These properties set the amount to wander in the x and y directions.
+*/
+
+/*!
+ \qmlproperty int QFxParticleMotionWander::pace
+ This property holds how quickly the paricles will move from side to side.
+*/
+
+QML_DEFINE_TYPE(QFxParticleMotionWander,ParticleMotionWander)
+
+void QFxParticleMotionWander::advance(QFxParticle &p, int interval)
+{
+ if (!particles)
+ particles = qobject_cast<QFxParticles*>(parent());
+ if (particles) {
+ Data *d = (Data*)p.data;
+ if (_xvariance != 0.) {
+ qreal xdiff = p.x_velocity - d->x_targetV;
+ if ((xdiff > d->x_peak && d->x_var > 0.0) || (xdiff < -d->x_peak && d->x_var < 0.0)) {
+ d->x_var = -d->x_var;
+ d->x_peak = _xvariance + _xvariance * qreal(rand()) / RAND_MAX;
+ }
+ p.x_velocity += d->x_var * interval;
+ }
+ p.x += interval * p.x_velocity;
+
+ if (_yvariance != 0.) {
+ qreal ydiff = p.y_velocity - d->y_targetV;
+ if ((ydiff > d->y_peak && d->y_var > 0.0) || (ydiff < -d->y_peak && d->y_var < 0.0)) {
+ d->y_var = -d->y_var;
+ d->y_peak = _yvariance + _yvariance * qreal(rand()) / RAND_MAX;
+ }
+ p.y_velocity += d->y_var * interval;
+ }
+ p.y += interval * p.y_velocity;
+ }
+}
+
+void QFxParticleMotionWander::created(QFxParticle &p)
+{
+ if (!p.data) {
+ Data *d = new Data;
+ p.data = (void*)d;
+ d->x_targetV = p.x_velocity;
+ d->y_targetV = p.y_velocity;
+ d->x_peak = _xvariance;
+ d->y_peak = _yvariance;
+ d->x_var = _pace * qreal(rand()) / RAND_MAX / 1000.0;
+ d->y_var = _pace * qreal(rand()) / RAND_MAX / 1000.0;
+ }
+}
+
+void QFxParticleMotionWander::destroy(QFxParticle &p)
+{
+ if (p.data)
+ delete (Data*)p.data;
+}
+
+//---------------------------------------------------------------------------
+class QFxParticlesPainter : public QFxItem
+{
+public:
+ QFxParticlesPainter(QFxParticlesPrivate *p, QFxItem* parent)
+ : QFxItem(parent), d(p)
+ {
+ setOptions(HasContents);
+ maxX = minX = maxY = minY = 0;
+ }
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &p);
+#elif defined(QFX_RENDER_OPENGL2)
+ void paintGLContents(GLPainter &);
+#endif
+
+ void updateSize();
+
+ qreal maxX;
+ qreal minX;
+ qreal maxY;
+ qreal minY;
+ QFxParticlesPrivate* d;
+};
+
+//---------------------------------------------------------------------------
+class QFxParticlesPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxParticles)
+public:
+ QFxParticlesPrivate()
+ : count(1), lifeSpan(1000), lifeSpanDev(1000), fadeInDur(200), fadeOutDur(300)
+ , angle(0), angleDev(0), velocity(0), velocityDev(0)
+ , addParticleTime(0), addParticleCount(0), lastAdvTime(0), stream(false), streamDelay(0)
+ , emitting(true), motion(0), clock(this)
+#if defined(QFX_RENDER_OPENGL)
+ , texDirty(true)
+#endif
+ {
+ }
+
+ ~QFxParticlesPrivate()
+ {
+ }
+
+ void init()
+ {
+ Q_Q(QFxParticles);
+ paintItem = new QFxParticlesPainter(this, q);
+ }
+
+ void tick(int time);
+ void createParticle(int time);
+ void updateOpacity(QFxParticle &p, int age);
+
+ QString source;
+ QUrl url;
+ QPixmap image;
+ int count;
+ int lifeSpan;
+ int lifeSpanDev;
+ int fadeInDur;
+ int fadeOutDur;
+ qreal angle;
+ qreal angleDev;
+ qreal velocity;
+ qreal velocityDev;
+ int addParticleTime;
+ int addParticleCount;
+ int lastAdvTime;
+ bool stream;
+ int streamDelay;
+ bool emitting;
+ QFxParticleMotion *motion;
+ QFxParticlesPainter *paintItem;
+
+ QList<QFxParticle> particles;
+ QTickAnimationProxy<QFxParticlesPrivate, &QFxParticlesPrivate::tick> clock;
+
+#if defined(QFX_RENDER_OPENGL)
+ bool texDirty;
+ GLTexture tex;
+#endif
+};
+
+//TODO: Stop the clock if no visible particles and not emitting (restart on emittingChanged)
+void QFxParticlesPrivate::tick(int time)
+{
+ Q_Q(QFxParticles);
+ if (!motion)
+ motion = new QFxParticleMotionLinear(q);
+
+ int oldCount = particles.count();
+ int removed = 0;
+ int interval = time - lastAdvTime;
+ for (int i = 0; i < particles.count(); ) {
+ QFxParticle &particle = particles[i];
+ int age = time - particle.birthTime;
+ if (age >= particle.lifeSpan) {
+ QFxParticle part = particles.takeAt(i);
+ motion->destroy(part);
+ ++removed;
+ } else {
+ updateOpacity(particle, age);
+ motion->advance(particle, interval);
+ ++i;
+ }
+ }
+
+ while(removed-- && particles.count() < count && emitting)
+ createParticle(time);
+
+ if (!addParticleTime)
+ addParticleTime = time;
+
+ if (particles.count() < count && emitting) {
+ qreal perc = (lifeSpanDev <= 0)?(1.):(qreal(time - addParticleTime) / qreal(lifeSpanDev));
+ int percCount = addParticleCount + (int)perc * (count - addParticleCount);
+ int streamWidth = -1;
+ if (stream){
+ if (streamDelay > time){
+ streamWidth = 0;
+ }else{
+ int missed = time - streamDelay;
+ qreal streamWidthReal = qreal(count)/qreal(lifeSpan);
+ if (streamWidthReal < 1){
+ streamDelay = time + (int)(1.0/streamWidthReal);
+ streamWidth = 1;
+ streamWidth += missed/streamDelay;
+ }else{
+ streamWidth = qRound(streamWidthReal * (time-lastAdvTime));
+ }
+ }
+ }
+ while(particles.count() < count && particles.count() < percCount && streamWidth--)
+ createParticle(time);
+ }
+
+ lastAdvTime = time;
+ if (oldCount || particles.count()) {
+ if (q->itemParent())
+ q->itemParent()->update();
+ else
+ q->update();
+ } else if (!count) {
+ lastAdvTime = 0;
+ clock.stop();
+ }
+}
+
+void QFxParticlesPrivate::createParticle(int time)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::CreateParticle> x;
+#endif
+ Q_Q(QFxParticles);
+ QFxParticle p(time);
+ p.x = q->x() + q->width() * qreal(rand()) / RAND_MAX - image.width()/2.0;
+ p.y = q->y() + q->height() * qreal(rand()) / RAND_MAX - image.height()/2.0;
+ p.lifeSpan = lifeSpan;
+ if (lifeSpanDev)
+ p.lifeSpan += int(lifeSpanDev/2 - lifeSpanDev * qreal(rand()) / RAND_MAX);
+ p.fadeOutAge = p.lifeSpan - fadeOutDur;
+ if (fadeInDur == 0.) {
+ p.state= QFxParticle::Solid;
+ p.opacity = 1.0;
+ }
+ qreal a = angle;
+ if (angleDev)
+ a += angleDev/2 - angleDev * qreal(rand()) / RAND_MAX;
+ if (a > M_PI)
+ a = a - 2 * M_PI;
+ qreal v = velocity;
+ if (velocityDev)
+ v += velocityDev/2 - velocityDev * qreal(rand()) / RAND_MAX;
+ p.x_velocity = v * fastCos(a);
+ p.y_velocity = v * fastSin(a);
+ particles.append(p);
+ motion->created(particles.last());
+}
+
+void QFxParticlesPrivate::updateOpacity(QFxParticle &p, int age)
+{
+ switch (p.state) {
+ case QFxParticle::FadeIn:
+ if (age <= fadeInDur) {
+ p.opacity = qreal(age) / fadeInDur;
+ break;
+ } else {
+ p.opacity = 1.0;
+ p.state = QFxParticle::Solid;
+ // Fall through
+ }
+ case QFxParticle::Solid:
+ if (age <= p.fadeOutAge) {
+ break;
+ } else {
+ p.state = QFxParticle::FadeOut;
+ // Fall through
+ }
+ case QFxParticle::FadeOut:
+ p.opacity = qreal(p.lifeSpan - age) / fadeOutDur;
+ break;
+ }
+}
+
+QML_DEFINE_TYPE(QFxParticles,Particles)
+
+/*!
+ \qmlclass Particles
+ \brief The Particles object generates and moves particles.
+ \inherits Item
+
+ The particles created by this object cannot be dealt with directly, they can only be controlled through the parameters of the Particles object. The particles are all the same pixmap, specified by the user.
+
+ The particles are painted relative to the parent of the Particles object. Moving the
+ Particles object will not move the particles already emitted.
+
+ The below example creates two differently behaving particle sources.
+ The top one has particles falling from the top like snow,
+ the lower one has particles expelled up like a fountain.
+
+ \qml
+Rect {
+ width: 240
+ height: 320
+ color: "black"
+ Particles {
+ y: 0
+ width: parent.width
+ height: 30
+ source: "star.png"
+ lifeSpan: 5000
+ count: 50
+ angle: 70
+ angleDeviation: 36
+ velocity: 30
+ velocityDeviation: 10
+ ParticleMotionWander {
+ xvariance: 30
+ pace: 100
+ }
+ }
+ Particles {
+ y: 300
+ x: 120
+ width: 1
+ height: 1
+ source: "star.png"
+ lifeSpan: 5000
+ count: 200
+ angle: 270
+ angleDeviation: 45
+ velocity: 50
+ velocityDeviation: 30
+ ParticleMotionGravity {
+ yattractor: 1000
+ xattractor: 0
+ acceleration: 25
+ }
+ }
+}
+ \endqml
+ \image particles.gif
+*/
+
+/*!
+ \internal
+ \class QFxParticles
+ \ingroup group_effects
+ \brief The QFxParticles class generates and moves particles.
+*/
+
+QFxParticles::QFxParticles(QFxItem *parent)
+ : QFxItem(*(new QFxParticlesPrivate), parent)
+{
+ Q_D(QFxParticles);
+ d->init();
+ setOptions(HasContents);
+}
+
+QFxParticles::QFxParticles(QFxParticlesPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxParticles);
+ d->init();
+ setOptions(HasContents);
+}
+
+QFxParticles::~QFxParticles()
+{
+}
+
+/*!
+ \qmlproperty string Particles::src
+ This property holds the URL of the particle image.
+*/
+
+/*!
+ \property QFxParticles::source
+ \brief the URL of the particle image.
+*/
+QString QFxParticles::source() const
+{
+ Q_D(const QFxParticles);
+ return d->source;
+}
+
+void QFxParticles::imageLoaded()
+{
+ Q_D(QFxParticles);
+ d->image = QFxPixmap(d->url);
+#if defined(QFX_RENDER_OPENGL)
+ d->texDirty = true;
+ d->tex.clear();
+#endif
+ update();
+}
+
+void QFxParticles::setSource(const QString &name)
+{
+ Q_D(QFxParticles);
+
+ if (name == d->source)
+ return;
+
+ if (!d->source.isEmpty())
+ QFxPixmap::cancelGet(d->url, this);
+ if (name.isEmpty()) {
+ d->source = name;
+ d->url = QUrl();
+ d->image = QPixmap();
+#if defined(QFX_RENDER_OPENGL)
+ d->texDirty = true;
+ d->tex.clear();
+#endif
+ update();
+ } else {
+ d->source = name;
+ d->url = qmlContext(this)->resolvedUrl(name);
+ QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(imageLoaded()));
+ }
+}
+
+/*!
+ \qmlproperty int Particles::count
+ This property holds the target number of particles
+*/
+
+/*!
+ \property QFxParticles::count
+ \brief the target number of particles
+*/
+int QFxParticles::count() const
+{
+ Q_D(const QFxParticles);
+ return d->count;
+}
+
+void QFxParticles::setCount(int cnt)
+{
+ Q_D(QFxParticles);
+ if (cnt != d->count) {
+ if (!d->count && d->clock.state() != QAbstractAnimation::Running)
+ d->clock.start(); // infinity??
+ d->count = cnt;
+ d->addParticleTime = 0;
+ d->addParticleCount = d->particles.count();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty int Particles::lifeSpan
+ \qmlproperty int Particles::lifeSpanDeviation
+
+ These properties describe the life span of each particle.
+
+ The default lifespan for a particle is 1000ms.
+
+ lifeSpanDeviation randomly varies the lifeSpan up to the specified variation. For
+ example, the following creates particles whose lifeSpan will vary
+ from 150ms to 250ms:
+
+ \qml
+Particles {
+ source: "star.png"
+ lifeSpan: 200
+ lifeSpanDeviation: 100
+}
+ \endqml
+*/
+
+/*!
+ \property QFxParticles::lifeSpan
+ \brief the life span of each particle.
+
+ Default value is 1000ms.
+
+ \sa QFxParticles::lifeSpanDeviation
+*/
+int QFxParticles::lifeSpan() const
+{
+ Q_D(const QFxParticles);
+ return d->lifeSpan;
+}
+
+void QFxParticles::setLifeSpan(int ls)
+{
+ Q_D(QFxParticles);
+ d->lifeSpan = ls;
+}
+
+/*!
+ \property QFxParticles::lifeSpanDeviation
+ \brief the maximum possible deviation from the set lifeSpan.
+
+ Randomly varies the lifeSpan up to the specified variation. For
+ example, the following creates particles whose lifeSpan will vary
+ from 150ms to 250ms:
+
+\qml
+Particles {
+ source: "star.png"
+ lifeSpan: 200
+ lifeSpanDeviation: 100
+}
+\endqml
+
+ \sa QFxParticles::lifeSpan
+*/
+int QFxParticles::lifeSpanDeviation() const
+{
+ Q_D(const QFxParticles);
+ return d->lifeSpanDev;
+}
+
+void QFxParticles::setLifeSpanDeviation(int dev)
+{
+ Q_D(QFxParticles);
+ d->lifeSpanDev = dev;
+}
+
+/*!
+ \qmlproperty int Particles::fadeInDuration
+ \qmlproperty int Particles::fadeOutDuration
+ These properties hold the time taken to fade the particles in and out.
+
+ By default fade in is 200ms and fade out is 300ms.
+*/
+
+/*!
+ \property QFxParticles::fadeInDuration
+ \brief the time taken to fade in the particles.
+
+ Default value is 200ms.
+*/
+int QFxParticles::fadeInDuration() const
+{
+ Q_D(const QFxParticles);
+ return d->fadeInDur;
+}
+
+void QFxParticles::setFadeInDuration(int dur)
+{
+ Q_D(QFxParticles);
+ if (dur >= 0.0)
+ d->fadeInDur = dur;
+}
+
+/*!
+ \property QFxParticles::fadeOutDuration
+ \brief the time taken to fade out the particles.
+
+ Default value is 300ms.
+*/
+int QFxParticles::fadeOutDuration() const
+{
+ Q_D(const QFxParticles);
+ return d->fadeOutDur;
+}
+
+void QFxParticles::setFadeOutDuration(int dur)
+{
+ Q_D(QFxParticles);
+ if (dur >= 0.0)
+ d->fadeOutDur = dur;
+}
+
+/*!
+ \qmlproperty real Particles::angle
+ \qmlproperty real Particles::angleDeviation
+
+ These properties control particle direction.
+
+ angleDeviation randomly varies the direction up to the specified variation. For
+ example, the following creates particles whose initial direction will
+ vary from 15 degrees to 105 degrees:
+
+ \qml
+Particles {
+ source: "star.png"
+ angle: 60
+ angleDeviation: 90
+}
+ \endqml
+*/
+
+/*!
+ \property QFxParticles::angle
+ \brief the initial angle of direction.
+
+ \sa QFxParticles::angleDeviation
+*/
+qreal QFxParticles::angle() const
+{
+ Q_D(const QFxParticles);
+ return d->angle * 180.0 / M_PI;
+}
+
+void QFxParticles::setAngle(qreal angle)
+{
+ Q_D(QFxParticles);
+ d->angle = angle * M_PI / 180.0;
+}
+
+/*!
+ \property QFxParticles::angleDeviation
+ \brief the maximum possible deviation from the set angle.
+
+ Randomly varies the direction up to the specified variation. For
+ example, the following creates particles whose initial direction will
+ vary from 15 degrees to 105 degrees:
+
+\qml
+Particles {
+ source: "star.png"
+ angle: 60
+ angleDeviation: 90
+}
+\endqml
+
+ \sa QFxParticles::angle
+*/
+qreal QFxParticles::angleDeviation() const
+{
+ Q_D(const QFxParticles);
+ return d->angleDev * 180.0 / M_PI;
+}
+
+void QFxParticles::setAngleDeviation(qreal dev)
+{
+ Q_D(QFxParticles);
+ d->angleDev = dev * M_PI / 180.0;;
+}
+
+/*!
+ \qmlproperty real Particles::velocity
+ \qmlproperty real Particles::velocityDeviation
+
+ These properties control the velocity of the particles.
+
+ velocityDeviation randomly varies the velocity up to the specified variation. For
+ example, the following creates particles whose initial velocity will
+ vary from 40 to 60.
+
+ \qml
+Particles {
+ source: "star.png"
+ velocity: 50
+ velocityDeviation: 20
+}
+ \endqml
+*/
+
+/*!
+ \property QFxParticles::velocity
+ \brief the initial velocity of the particles.
+
+ \sa QFxParticles::velocityDeviation
+*/
+qreal QFxParticles::velocity() const
+{
+ Q_D(const QFxParticles);
+ return d->velocity * 1000.0;
+}
+
+void QFxParticles::setVelocity(qreal velocity)
+{
+ Q_D(QFxParticles);
+ d->velocity = velocity / 1000.0;
+}
+
+/*!
+ \property QFxParticles::velocityDeviation
+ \brief the maximum possible deviation from the set velocity.
+
+ Randomly varies the velocity up to the specified variation. For
+ example, the following creates particles whose initial velocity will
+ vary from 40 to 60.
+
+\qml
+Particles {
+ source: "star.png"
+ velocity: 50
+ velocityDeviation: 20
+}
+\endqml
+
+ \sa QFxParticles::velocity
+*/
+qreal QFxParticles::velocityDeviation() const
+{
+ Q_D(const QFxParticles);
+ return d->velocityDev * 1000.0;
+}
+
+void QFxParticles::setVelocityDeviation(qreal velocity)
+{
+ Q_D(QFxParticles);
+ d->velocityDev = velocity / 1000.0;
+}
+
+/*!
+ \qmlproperty bool Particles::streamIn
+ This property determines whether the particles stream in at a constant rate
+
+ When stream is set to true the particles will stream in at a constant rate.
+ Otherwise the particles will appear as a clump. Note that this only affects the
+ start of the particle effect, variables such as lifespan deviation can cause the
+ particles to unclump over time.
+*/
+/*!
+ \property QFxParticles::streamIn
+ \brief determines whether the particles stream in at a constant rate
+
+ When stream is set to true the particles will stream in at a constant rate.
+ Otherwise the particles will appear as a clump. Note that this only affects the
+ start of the particle effect, variables such as lifespan deviation can cause the
+
+*/
+//The name may need a rethink
+bool QFxParticles::streamIn() const
+{
+ Q_D(const QFxParticles);
+ return d->stream;
+}
+
+void QFxParticles::setStreamIn(bool b)
+{
+ Q_D(QFxParticles);
+ d->stream = b;
+}
+
+/*!
+ \qmlproperty bool Particles::emitting
+ This property determines whether new particles are created
+
+ If emitting is set to false no new particles will be created. This means that
+ when a particle reaches the end of its lifespan it is not replaced. This
+ property can be used to turn particles on and off with a more natural look.
+
+ The default setting is true. Note that if it initialized to false no particles
+ will be produced until it is set to true.
+*/
+/*!
+ \property QFxParticles::emitting
+ If emitting is set to false no new particles will be created. This means that
+ when a particle reaches the end of its lifespan it is not replaced. This
+ property can be used to turn particles on and off with a more natural look.
+
+ The default setting is true. Note that if it initialized to false no particles
+ will be produced until it is set to true.
+*/
+bool QFxParticles::emitting() const
+{
+ Q_D(const QFxParticles);
+ return d->emitting;
+}
+
+void QFxParticles::setEmitting(bool r)
+{
+ Q_D(QFxParticles);
+ d->emitting = r;
+}
+/*!
+ \qmlproperty ParticleMotion Particles::motion
+ This property sets the type of motion to apply to the particles.
+
+ When a particle is created it will have an initial direction and velocity.
+ The motion of the particle during its lifeSpan is then influenced by the
+ motion property.
+
+ Default motion is ParticleMotionLinear.
+*/
+
+/*!
+ \property QFxParticles::motion
+ \brief sets the type of motion to apply to the particles.
+
+ When a particle is created it will have an initial direction and velocity.
+ The motion of the particle during its lifeSpan is then influenced by the
+ motion property.
+
+ Default motion is QFxParticleMotionLinear.
+*/
+QFxParticleMotion *QFxParticles::motion() const
+{
+ Q_D(const QFxParticles);
+ return d->motion;
+}
+
+void QFxParticles::setMotion(QFxParticleMotion *motion)
+{
+ Q_D(QFxParticles);
+ d->motion = motion;
+}
+
+void QFxParticles::dump(int depth)
+{
+ Q_D(QFxParticles);
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "URL:" << d->url << "Count:" << d->count;
+ QFxItem::dump(depth);
+}
+
+QString QFxParticles::propertyInfo() const
+{
+ Q_D(const QFxParticles);
+ return d->url.toString();
+}
+
+void QFxParticlesPainter::updateSize(){
+ setX(-500);
+ setY(-500);
+ setWidth(1000);
+ setHeight(1000);
+ return ;
+ const int parentX = parent()->x();
+ const int parentY = parent()->y();
+ //Have to use statistical approach to needed size as arbitrary particle
+ //motions make it impossible to calculate.
+ //max/min vars stored to give a never shrinking rect
+ for (int i = 0; i < d->particles.count(); ++i) {
+ const QFxParticle &particle = d->particles.at(i);
+ if(particle.x > maxX)
+ maxX = particle.x;
+ if(particle.x < minX)
+ minX = particle.x;
+ if(particle.y > maxY)
+ maxY = particle.y;
+ if(particle.y < minY)
+ minY = particle.y;
+ }
+
+ int myWidth = (int)(maxX-minX+0.5)+d->image.width();
+ int myX = (int)(minX - parentX);
+ int myHeight = (int)(maxY-minY+0.5)+d->image.height();
+ int myY = (int)(minY - parentY);
+ setWidth(myWidth);
+ setHeight(myHeight);
+ setX(myX);
+ setY(myY);
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxParticles::paintContents(QPainter &p)
+{
+ Q_UNUSED(p);
+ //painting is done by the ParticlesPainter, so it can have the right size
+}
+
+void QFxParticlesPainter::paintContents(QPainter &p)
+{
+ if (d->image.isNull())
+ return;
+
+ updateSize();
+ const int myX = x() + parent()->x();
+ const int myY = y() + parent()->y();
+
+ for (int i = 0; i < d->particles.count(); ++i) {
+ const QFxParticle &particle = d->particles.at(i);
+ p.setOpacity(particle.opacity);
+ p.drawPixmap(particle.x - myX, particle.y - myY, d->image);
+ }
+ update();//Should I need this? (GV does)
+}
+#elif defined(QFX_RENDER_OPENGL2)
+void QFxParticles::paintGLContents(GLPainter &)
+{
+ //painting is done by the ParticlesPainter, so it can have the right size
+}
+
+void QFxParticlesPainter::paintGLContents(GLPainter &p)
+{
+
+ if (d->image.isNull())
+ return;
+
+ updateSize();
+
+ if (d->texDirty && !d->image.isNull()) {
+ d->tex.setImage(d->image.toImage());
+ d->tex.setHorizontalWrap(GLTexture::Repeat);
+ d->tex.setVerticalWrap(GLTexture::Repeat);
+ }
+ d->texDirty = false;
+
+ SingleTextureOpacityShader *shader = basicShaders()->singleTextureOpacity();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+
+ const int myX = (int)(x() + parent()->x());
+ const int myY = (int)(y() + parent()->y());
+ float widthV = d->image.width();
+ float heightV = d->image.height();
+ for (int i = 0; i < d->particles.count(); ++i) {
+ const QFxParticle &particle = d->particles.at(i);
+ float left = particle.x - myX;
+ float right = particle.x - myX + widthV;
+ float top = particle.y - myY;
+ float bottom = particle.y - myY + heightV;
+
+ GLfloat vertices[] = { left, bottom,
+ right, bottom,
+ left, top,
+ right, top };
+
+ GLfloat texVertices[] = { 0, 0,
+ 1, 0,
+ 0, 1,
+ 1, 1 };
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+ shader->setOpacity(particle.opacity * p.activeOpacity);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+}
+#endif
+
+void QFxParticles::componentComplete()
+{
+ Q_D(QFxParticles);
+ QFxItem::componentComplete();
+ if (d->count)
+ d->clock.start(); // infinity??
+ if (d->lifeSpanDev > d->lifeSpan)
+ d->lifeSpanDev = d->lifeSpan;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxparticles.h b/src/declarative/fx/qfxparticles.h
new file mode 100644
index 0000000..6ef2582
--- /dev/null
+++ b/src/declarative/fx/qfxparticles.h
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPARTICLES_H
+#define QFXPARTICLES_H
+
+#include <QtDeclarative/qfxitem.h>
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxParticle;
+class QFxParticles;
+class Q_DECLARATIVE_EXPORT QFxParticleMotion : public QObject
+{
+ Q_OBJECT
+public:
+ QFxParticleMotion(QObject *parent=0);
+
+ virtual void advance(QFxParticle &, int interval);
+ virtual void created(QFxParticle &);
+ virtual void destroy(QFxParticle &);
+};
+QML_DECLARE_TYPE(QFxParticleMotion)
+
+class Q_DECLARATIVE_EXPORT QFxParticleMotionLinear : public QFxParticleMotion
+{
+ Q_OBJECT
+public:
+ QFxParticleMotionLinear(QObject *parent=0)
+ : QFxParticleMotion(parent) {}
+
+ virtual void advance(QFxParticle &, int interval);
+};
+QML_DECLARE_TYPE(QFxParticleMotionLinear)
+
+class Q_DECLARATIVE_EXPORT QFxParticleMotionGravity : public QFxParticleMotion
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int xattractor READ xAttractor WRITE setXAttractor)
+ Q_PROPERTY(int yattractor READ yAttractor WRITE setYAttractor)
+ Q_PROPERTY(int acceleration READ acceleration WRITE setAcceleration)
+public:
+ QFxParticleMotionGravity(QObject *parent=0)
+ : QFxParticleMotion(parent), _xAttr(0), _yAttr(0), _accel(0.00005) {}
+
+ int xAttractor() const { return _xAttr; }
+ void setXAttractor(int x) { _xAttr = x; }
+
+ int yAttractor() const { return _yAttr; }
+ void setYAttractor(int y) { _yAttr = y; }
+
+ int acceleration() const { return int(_accel * 1000000); }
+ void setAcceleration(int accel) { _accel = qreal(accel)/1000000.0; }
+
+ virtual void advance(QFxParticle &, int interval);
+
+private:
+ int _xAttr;
+ int _yAttr;
+ qreal _accel;
+};
+QML_DECLARE_TYPE(QFxParticleMotionGravity)
+
+class Q_DECLARATIVE_EXPORT QFxParticleMotionWander : public QFxParticleMotion
+{
+ Q_OBJECT
+public:
+ QFxParticleMotionWander()
+ : QFxParticleMotion(), particles(0), _xvariance(0), _yvariance(0) {}
+
+ virtual void advance(QFxParticle &, int interval);
+ virtual void created(QFxParticle &);
+ virtual void destroy(QFxParticle &);
+
+ struct Data {
+ qreal x_targetV;
+ qreal y_targetV;
+ qreal x_peak;
+ qreal y_peak;
+ qreal x_var;
+ qreal y_var;
+ };
+
+ Q_PROPERTY(int xvariance READ xVariance WRITE setXVariance)
+ int xVariance() const { return int(_xvariance * 1000); }
+ void setXVariance(int var) { _xvariance = var / 1000.0; }
+
+ Q_PROPERTY(int yvariance READ yVariance WRITE setYVariance)
+ int yVariance() const { return int(_yvariance * 1000); }
+ void setYVariance(int var) { _yvariance = var / 1000.0; }
+
+ Q_PROPERTY(int pace READ pace WRITE setPace)
+ int pace() const { return int(_pace * 1000); }
+ void setPace(int pace) { _pace = pace / 1000.0; }
+
+private:
+ QFxParticles *particles;
+ qreal _xvariance;
+ qreal _yvariance;
+ qreal _pace;
+};
+QML_DECLARE_TYPE(QFxParticleMotionWander)
+
+class QFxParticlesPrivate;
+class Q_DECLARATIVE_EXPORT QFxParticles : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString source READ source WRITE setSource)
+ Q_PROPERTY(int count READ count WRITE setCount)
+ Q_PROPERTY(int lifeSpan READ lifeSpan WRITE setLifeSpan)
+ Q_PROPERTY(int lifeSpanDeviation READ lifeSpanDeviation WRITE setLifeSpanDeviation)
+ Q_PROPERTY(int fadeInDuration READ fadeInDuration WRITE setFadeInDuration)
+ Q_PROPERTY(int fadeOutDuration READ fadeOutDuration WRITE setFadeOutDuration)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle)
+ Q_PROPERTY(qreal angleDeviation READ angleDeviation WRITE setAngleDeviation)
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity)
+ Q_PROPERTY(qreal velocityDeviation READ velocityDeviation WRITE setVelocityDeviation)
+ Q_PROPERTY(bool streamIn READ streamIn WRITE setStreamIn)
+ Q_PROPERTY(bool emitting READ emitting WRITE setEmitting)
+ Q_PROPERTY(QFxParticleMotion *motion READ motion WRITE setMotion)
+ Q_CLASSINFO("DefaultProperty", "motion")
+
+public:
+ QFxParticles(QFxItem *parent=0);
+ ~QFxParticles();
+
+ QString source() const;
+ void setSource(const QString &);
+
+ int count() const;
+ void setCount(int cnt);
+
+ int lifeSpan() const;
+ void setLifeSpan(int);
+
+ int lifeSpanDeviation() const;
+ void setLifeSpanDeviation(int);
+
+ int fadeInDuration() const;
+ void setFadeInDuration(int);
+
+ int fadeOutDuration() const;
+ void setFadeOutDuration(int);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ qreal angleDeviation() const;
+ void setAngleDeviation(qreal);
+
+ qreal velocity() const;
+ void setVelocity(qreal);
+
+ qreal velocityDeviation() const;
+ void setVelocityDeviation(qreal);
+
+ bool streamIn() const;
+ void setStreamIn(bool);
+
+ bool emitting() const;
+ void setEmitting(bool);
+
+ QFxParticleMotion *motion() const;
+ void setMotion(QFxParticleMotion *);
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &p);
+#elif defined(QFX_RENDER_OPENGL2)
+ void paintGLContents(GLPainter &);
+#endif
+
+protected:
+ virtual void componentComplete();
+ QFxParticles(QFxParticlesPrivate &dd, QFxItem *parent);
+
+private Q_SLOTS:
+ void imageLoaded();
+
+private:
+ Q_DISABLE_COPY(QFxParticles)
+ Q_DECLARE_PRIVATE(QFxParticles)
+};
+QML_DECLARE_TYPE(QFxParticles)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/fx/qfxpath.cpp b/src/declarative/fx/qfxpath.cpp
new file mode 100644
index 0000000..be731b1
--- /dev/null
+++ b/src/declarative/fx/qfxpath.cpp
@@ -0,0 +1,868 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxpath.h"
+#include "qfxpath_p.h"
+#include <qfxperf.h>
+#include <private/qbezier_p.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxPath,Path)
+QML_DEFINE_NOCREATE_TYPE(QFxPathElement)
+QML_DEFINE_NOCREATE_TYPE(QFxCurve)
+QML_DEFINE_TYPE(QFxPathAttribute,PathAttribute)
+QML_DEFINE_TYPE(QFxPathPercent,PathPercent)
+QML_DEFINE_TYPE(QFxPathLine,PathLine)
+QML_DEFINE_TYPE(QFxPathQuad,PathQuad)
+QML_DEFINE_TYPE(QFxPathCubic,PathCubic)
+
+/*!
+ \qmlclass PathElement
+ \brief PathElement is the base path type.
+
+ This type is the base for all path types. It cannot
+ be instantiated.
+
+ \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QFxPathElement
+ \ingroup group_utility
+*/
+
+/*!
+ \qmlclass Path QFxPath
+ \brief A Path object defines a path for use by \l PathView.
+
+ A Path is composed of one or more path segments - PathLine, PathQuad,
+ PathCubic.
+
+ The spacing of the items along the Path can be adjusted via a
+ PathPercent object.
+
+ PathAttribute allows named attributes with values to be defined
+ along the path.
+
+ \sa PathView, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QFxPath
+ \ingroup group_utility
+ \brief The QFxPath class defines a path.
+ \sa QFxPathView
+*/
+QFxPath::QFxPath(QObject *parent)
+ : QObject(*(new QFxPathPrivate), parent)
+{
+}
+
+QFxPath::QFxPath(QFxPathPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+QFxPath::~QFxPath()
+{
+}
+
+/*!
+ \qmlproperty real Path::startX
+ \qmlproperty real Path::startY
+ This property holds the starting position of the path.
+*/
+
+/*!
+ \property QFxPath::startX
+ \brief the starting x position of the path.
+*/
+
+qreal QFxPath::startX() const
+{
+ Q_D(const QFxPath);
+ return d->startX;
+}
+
+void QFxPath::setStartX(qreal x)
+{
+ Q_D(QFxPath);
+ d->startX = x;
+}
+
+
+/*!
+ \property QFxPath::startY
+ \brief the starting y position of the path.
+*/
+
+qreal QFxPath::startY() const
+{
+ Q_D(const QFxPath);
+ return d->startY;
+}
+
+void QFxPath::setStartY(qreal y)
+{
+ Q_D(QFxPath);
+ d->startY = y;
+}
+
+/*!
+ \qmlproperty list<PathElement> Path::pathElements
+ This property holds the objects composing the path.
+
+ \default
+
+ A path can contain the following path objects:
+ \list
+ \i \l PathLine - a straight line to a given position.
+ \i \l PathQuad - a quadratic Bezier curve to a given position with a control point.
+ \i \l PathCubic - a cubic Bezier curve to a given position with two control points.
+ \i \l PathAttribute - an attribute at a given position in the path.
+ \i \l PathPercent - a way to spread out items along various segments of the path.
+ \endlist
+
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 2
+*/
+
+QList<QFxPathElement *>* QFxPath::pathElements()
+{
+ Q_D(QFxPath);
+ return &(d->_pathElements);
+}
+
+void QFxPath::interpolate(int idx, const QString &name, qreal value)
+{
+ Q_D(QFxPath);
+ if (!idx)
+ return;
+
+ qreal lastValue = 0;
+ qreal lastPercent = 0;
+ int search = idx - 1;
+ while(search >= 0) {
+ const AttributePoint &point = d->_attributePoints.at(search);
+ if (point.values.contains(name)) {
+ lastValue = point.values.value(name);
+ lastPercent = point.origpercent;
+ break;
+ }
+ --search;
+ }
+
+ ++search;
+
+ const AttributePoint &curPoint = d->_attributePoints.at(idx);
+
+ for (int ii = search; ii < idx; ++ii) {
+ AttributePoint &point = d->_attributePoints[ii];
+
+ qreal val = lastValue + (value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
+ point.values.insert(name, val);
+ }
+}
+
+void QFxPath::endpoint(const QString &name)
+{
+ Q_D(QFxPath);
+ const AttributePoint &first = d->_attributePoints.first();
+ qreal val = first.values.value(name);
+ for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(name)) {
+ for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
+ AttributePoint &setPoint = d->_attributePoints[jj];
+ setPoint.values.insert(name, val);
+ }
+ return;
+ }
+ }
+}
+
+void QFxPath::processPath()
+{
+ Q_D(QFxPath);
+
+ d->_pointCache.clear();
+ d->_attributePoints.clear();
+ d->_path = QPainterPath();
+
+ AttributePoint first;
+ for (int ii = 0; ii < d->_attributes.count(); ++ii)
+ first.values[d->_attributes.at(ii)] = 0;
+ d->_attributePoints << first;
+
+ d->_path.moveTo(d->startX, d->startY);
+
+ foreach (QFxPathElement *pathElement, d->_pathElements) {
+ if (QFxCurve *curve = qobject_cast<QFxCurve *>(pathElement)) {
+ curve->addToPath(d->_path);
+ AttributePoint p;
+ p.origpercent = d->_path.length();
+ d->_attributePoints << p;
+ } else if (QFxPathAttribute *attribute = qobject_cast<QFxPathAttribute *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[attribute->name()] = attribute->value();
+ interpolate(d->_attributePoints.count() - 1, attribute->name(), attribute->value());
+ } else if (QFxPathPercent *percent = qobject_cast<QFxPathPercent *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[QLatin1String("_qfx_percent")] = percent->value();
+ interpolate(d->_attributePoints.count() - 1, QLatin1String("_qfx_percent"), percent->value());
+ }
+ }
+
+ // Fixup end points
+ const AttributePoint &last = d->_attributePoints.last();
+ for (int ii = 0; ii < d->_attributes.count(); ++ii) {
+ if (!last.values.contains(d->_attributes.at(ii)))
+ endpoint(d->_attributes.at(ii));
+ }
+
+ // Adjust percent
+ qreal length = d->_path.length();
+ qreal prevpercent = 0;
+ qreal prevorigpercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(QLatin1String("_qfx_percent"))) { //special string for QFxPathPercent
+ if ( ii > 0) {
+ qreal scale = (d->_attributePoints[ii].origpercent/length - prevorigpercent) /
+ (point.values.value(QLatin1String("_qfx_percent"))-prevpercent);
+ d->_attributePoints[ii].scale = scale;
+ }
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = point.values.value(QLatin1String("_qfx_percent"));
+ prevorigpercent = d->_attributePoints[ii].origpercent;
+ prevpercent = d->_attributePoints[ii].percent;
+ } else {
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = d->_attributePoints[ii].origpercent;
+ }
+ }
+
+ emit changed();
+}
+
+void QFxPath::componentComplete()
+{
+ Q_D(QFxPath);
+ QSet<QString> attrs;
+ // First gather up all the attributes
+ foreach (QFxPathElement *pathElement, d->_pathElements) {
+ if (QFxPathAttribute *attribute =
+ qobject_cast<QFxPathAttribute *>(pathElement))
+ attrs.insert(attribute->name());
+ }
+ d->_attributes = attrs.toList();
+
+ processPath();
+
+ foreach (QFxPathElement *pathElement, d->_pathElements)
+ connect(pathElement, SIGNAL(changed()), this, SLOT(processPath()));
+}
+
+QPainterPath QFxPath::path() const
+{
+ Q_D(const QFxPath);
+ return d->_path;
+}
+
+QStringList QFxPath::attributes() const
+{
+ Q_D(const QFxPath);
+ return d->_attributes;
+}
+#include <QTime>
+
+static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength)
+{
+ const int lastElement = path.elementCount() - 1;
+ for (int i=*from; i <= lastElement; ++i) {
+ const QPainterPath::Element &e = path.elementAt(i);
+
+ switch (e.type) {
+ case QPainterPath::MoveToElement:
+ break;
+ case QPainterPath::LineToElement:
+ {
+ QLineF line(path.elementAt(i-1), e);
+ *bezLength = line.length();
+ QPointF a = path.elementAt(i-1);
+ QPointF delta = e - a;
+ *from = i+1;
+ return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
+ }
+ case QPainterPath::CurveToElement:
+ {
+ QBezier b = QBezier::fromPoints(path.elementAt(i-1),
+ e,
+ path.elementAt(i+1),
+ path.elementAt(i+2));
+ *bezLength = b.length();
+ *from = i+3;
+ return b;
+ }
+ default:
+ break;
+ }
+ }
+ *from = lastElement;
+ *bezLength = 0;
+ return QBezier();
+}
+
+void QFxPath::createPointCache() const
+{
+ Q_D(const QFxPath);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::QFxPathViewPathCache> pc;
+#endif
+ qreal pathLength = d->_path.length();
+ const int points = int(pathLength*2);
+ const int lastElement = d->_path.elementCount() - 1;
+ d->_pointCache.resize(points+1);
+
+ int currElement = 0;
+ qreal bezLength = 0;
+ QBezier currBez = nextBezier(d->_path, &currElement, &bezLength);
+ qreal currLength = bezLength;
+ qreal epc = currLength / pathLength;
+
+ for (int i = 0; i < d->_pointCache.size(); i++) {
+ //find which set we are in
+ qreal prevPercent = 0;
+ qreal prevOrigPercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ qreal percent = qreal(i)/points;
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
+ qreal elementPercent = (percent - prevPercent);
+
+ qreal spc = prevOrigPercent + elementPercent * point.scale;
+
+ while (spc > epc) {
+ if (currElement > lastElement)
+ break;
+ currBez = nextBezier(d->_path, &currElement, &bezLength);
+ if (bezLength == 0.0) {
+ currLength = pathLength;
+ epc = 1.0;
+ break;
+ }
+ currLength += bezLength;
+ epc = currLength / pathLength;
+ }
+ qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
+ d->_pointCache[i] = currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
+ break;
+ }
+ prevOrigPercent = point.origpercent;
+ prevPercent = point.percent;
+ }
+ }
+}
+
+QPointF QFxPath::pointAt(qreal p) const
+{
+ Q_D(const QFxPath);
+ if (d->_pointCache.isEmpty()) {
+ createPointCache();
+ }
+ int idx = qRound(p*d->_pointCache.size());
+ if (idx >= d->_pointCache.size())
+ idx = d->_pointCache.size() - 1;
+ else if (idx < 0)
+ idx = 0;
+ return d->_pointCache.at(idx);
+}
+
+qreal QFxPath::attributeAt(const QString &name, qreal percent) const
+{
+ Q_D(const QFxPath);
+ if (percent < 0 || percent > 1)
+ return 0;
+
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+
+ if (point.percent == percent) {
+ return point.values.value(name);
+ } else if (point.percent > percent) {
+ qreal lastValue =
+ ii?(d->_attributePoints.at(ii - 1).values.value(name)):0;
+ qreal lastPercent =
+ ii?(d->_attributePoints.at(ii - 1).percent):0;
+ qreal curValue = point.values.value(name);
+ qreal curPercent = point.percent;
+
+ return lastValue + (curValue - lastValue) * (percent - lastPercent) / (curPercent - lastPercent);
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+qreal QFxCurve::x() const
+{
+ return _x;
+}
+
+void QFxCurve::setX(qreal x)
+{
+ if (_x != x) {
+ _x = x;
+ emit changed();
+ }
+}
+
+qreal QFxCurve::y() const
+{
+ return _y;
+}
+
+void QFxCurve::setY(qreal y)
+{
+ if (_y != y) {
+ _y = y;
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathAttribute
+ \brief The PathAttribute allows setting an attribute at a given position in a Path.
+
+ The PathAttribute object allows attibutes consisting of a name and
+ a value to be specified for the endpoints of path segments. The
+ attributes are exposed to the delegate as
+ \l{qmlintroduction.html#attached-properties} {Attached Properties}.
+ The value of an attribute at any particular point is interpolated
+ from the PathAttributes bounding the point.
+
+ The example below shows a path with the items scaled to 30% with
+ opacity 50% at the top of the path and scaled 100% with opacity
+ 100% at the bottom. Note the use of the PathView.scale and
+ PathView.opacity attached properties to set the scale and opacity
+ of the delegate.
+
+ \table
+ \row
+ \o \image declarative-pathattribute.png
+ \o
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 0
+ \endtable
+
+ \sa Path
+*/
+
+/*!
+ \internal
+ \class QFxPathAttribute
+ \ingroup group_utility
+ \brief The QFxPathAttribute class allows to set the value of an attribute at a given position in the path.
+
+ \sa QFxPath
+*/
+
+
+/*!
+ \qmlproperty string PathAttribute::name
+ the name of the attribute to change.
+*/
+
+/*!
+ the name of the attribute to change.
+*/
+
+QString QFxPathAttribute::name() const
+{
+ return _name;
+}
+
+void QFxPathAttribute::setName(const QString &name)
+{
+ _name = name;
+}
+
+/*!
+ \qmlproperty string PathAttribute::value
+ the new value of the attribute.
+*/
+
+/*!
+ the new value of the attribute.
+*/
+qreal QFxPathAttribute::value() const
+{
+ return _value;
+}
+
+void QFxPathAttribute::setValue(qreal value)
+{
+ if (_value != value) {
+ _value = value;
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathLine
+ \brief The PathLine defines a straight line.
+
+ The example below creates a path consisting of a straight line from
+ 0,100 to 200,100:
+
+ \qml
+ Path {
+ startX: 0; startY: 100
+ PathLine { x: 200; y: 100 }
+ }
+ \endqml
+
+ \sa Path, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QFxPathLine
+ \ingroup group_utility
+ \brief The QFxPathLine class defines a straight line.
+
+ \sa QFxPath
+*/
+
+/*!
+ \qmlproperty real PathLine::x
+ \qmlproperty real PathLine::y
+
+ Defines the end point of the line.
+*/
+
+void QFxPathLine::addToPath(QPainterPath &path)
+{
+ path.lineTo(x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathQuad
+ \brief The PathQuad defines a quadratic Bezier curve with a control point.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathquad.png
+ \o
+ \qml
+ Path {
+ startX: 0; startY: 0
+ PathQuad x: 200; y: 0; controlX: 100; controlY: 150 }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathCubic, PathLine
+*/
+
+/*!
+ \internal
+ \class QFxPathQuad
+ \ingroup group_utility
+ \brief The QFxPathQuad class defines a quadratic Bezier curve with a control point.
+
+ \sa QFxPath
+*/
+
+
+/*!
+ \qmlproperty real PathQuad::x
+ \qmlproperty real PathQuad::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathQuad::controlX
+ \qmlproperty real PathQuad::controlY
+
+ Defines the position of the control point.
+*/
+
+/*!
+ the x position of the control point.
+*/
+qreal QFxPathQuad::controlX() const
+{
+ return _controlX;
+}
+
+void QFxPathQuad::setControlX(qreal x)
+{
+ if (_controlX != x) {
+ _controlX = x;
+ emit changed();
+ }
+}
+
+
+/*!
+ the y position of the control point.
+*/
+qreal QFxPathQuad::controlY() const
+{
+ return _controlY;
+}
+
+void QFxPathQuad::setControlY(qreal y)
+{
+ if (_controlY != y) {
+ _controlY = y;
+ emit changed();
+ }
+}
+
+void QFxPathQuad::addToPath(QPainterPath &path)
+{
+ path.quadTo(controlX(), controlY(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathCubic
+ \brief The PathCubic defines a cubic Bezier curve with two control points.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathcubic.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathCubic {
+ x: 180; y: 0; control1X: -10; control1Y: 90
+ control2X: 210; control2Y: 90
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathQuad, PathLine
+*/
+
+/*!
+ \internal
+ \class QFxPathCubic
+ \ingroup group_utility
+ \brief The QFxPathCubic class defines a cubic Bezier curve with two control points.
+
+ \sa QFxPath
+*/
+
+/*!
+ \qmlproperty real PathCubic::x
+ \qmlproperty real PathCubic::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathCubic::control1X
+ \qmlproperty real PathCubic::control1Y
+
+ Defines the position of the first control point.
+*/
+
+/*!
+ \property QFxPathCubic::control1X
+ \brief the x position of the first control point.
+*/
+qreal QFxPathCubic::control1X() const
+{
+ return _control1X;
+}
+
+void QFxPathCubic::setControl1X(qreal x)
+{
+ if (_control1X != x) {
+ _control1X = x;
+ emit changed();
+ }
+}
+
+/*!
+ \property QFxPathCubic::control1Y
+ \brief the y position of the first control point.
+*/
+qreal QFxPathCubic::control1Y() const
+{
+ return _control1Y;
+}
+
+void QFxPathCubic::setControl1Y(qreal y)
+{
+ if (_control1Y != y) {
+ _control1Y = y;
+ emit changed();
+ }
+}
+
+/*!
+ \qmlproperty real PathCubic::control2X
+ \qmlproperty real PathCubic::control2Y
+
+ Defines the position of the second control point.
+*/
+
+/*!
+ \property QFxPathCubic::control2X
+ \brief the x position of the second control point.
+*/
+qreal QFxPathCubic::control2X() const
+{
+ return _control2X;
+}
+
+void QFxPathCubic::setControl2X(qreal x)
+{
+ if (_control2X != x) {
+ _control2X = x;
+ emit changed();
+ }
+}
+
+/*!
+ \property QFxPathCubic::control2Y
+ \brief the y position of the second control point.
+*/
+qreal QFxPathCubic::control2Y() const
+{
+ return _control2Y;
+}
+
+void QFxPathCubic::setControl2Y(qreal y)
+{
+ if (_control2Y != y) {
+ _control2Y = y;
+ emit changed();
+ }
+}
+
+void QFxPathCubic::addToPath(QPainterPath &path)
+{
+ path.cubicTo(control1X(), control1Y(), control2X(), control2Y(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathPercent
+ \brief The PathPercent manipulates the way a path is interpreted.
+
+ The examples below show the normal distrubution of items along a path
+ compared to a distribution which places 50% of the items along the
+ PathLine section of the path.
+ \table
+ \row
+ \o \image declarative-nopercent.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ }
+ \endqml
+ \row
+ \o \image declarative-percent.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathPercent { value: 0.25 }
+ PathLine { x: 150; y: 80 }
+ PathPercent { value: 0.75 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ PathPercent { value: 1 }
+ }
+ \endqml
+ \endtable
+
+ \sa Path
+*/
+
+/*!
+ \internal
+ \class QFxPathPercent
+ \ingroup group_utility
+ \brief The QFxPathPercent class manipulates the way a path is interpreted.
+
+ QFxPathPercent allows you to bunch up items (or spread out items) along various
+ segments of a QFxPathView's path.
+
+ \sa QFxPath
+
+*/
+
+qreal QFxPathPercent::value() const
+{
+ return _value;
+}
+
+void QFxPathPercent::setValue(qreal value)
+{
+ _value = value;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpath.h b/src/declarative/fx/qfxpath.h
new file mode 100644
index 0000000..39b9d01
--- /dev/null
+++ b/src/declarative/fx/qfxpath.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATH_H
+#define QFXPATH_H
+
+#include <QtCore/QObject>
+#include <QtGui/QPainterPath>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxPathElement : public QObject
+{
+ Q_OBJECT
+public:
+ QFxPathElement(QObject *parent=0) : QObject(parent) {}
+Q_SIGNALS:
+ void changed();
+};
+QML_DECLARE_TYPE(QFxPathElement)
+
+class Q_DECLARATIVE_EXPORT QFxPathAttribute : public QFxPathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
+public:
+ QFxPathAttribute(QObject *parent=0) : QFxPathElement(parent), _value(0) {}
+
+
+ QString name() const;
+ void setName(const QString &name);
+
+ qreal value() const;
+ void setValue(qreal value);
+
+private:
+ QString _name;
+ qreal _value;
+};
+QML_DECLARE_TYPE(QFxPathAttribute)
+
+class Q_DECLARATIVE_EXPORT QFxCurve : public QFxPathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY changed)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY changed)
+public:
+ QFxCurve(QObject *parent=0) : QFxPathElement(parent), _x(0), _y(0) {}
+
+ qreal x() const;
+ void setX(qreal x);
+
+ qreal y() const;
+ void setY(qreal y);
+
+ virtual void addToPath(QPainterPath &) {}
+
+private:
+ qreal _x;
+ qreal _y;
+};
+QML_DECLARE_TYPE(QFxCurve)
+
+class Q_DECLARATIVE_EXPORT QFxPathLine : public QFxCurve
+{
+ Q_OBJECT
+public:
+ QFxPathLine(QObject *parent=0) : QFxCurve(parent) {}
+
+ void addToPath(QPainterPath &path);
+};
+QML_DECLARE_TYPE(QFxPathLine)
+
+class Q_DECLARATIVE_EXPORT QFxPathQuad : public QFxCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY changed)
+ Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY changed)
+public:
+ QFxPathQuad(QObject *parent=0) : QFxCurve(parent), _controlX(0), _controlY(0) {}
+
+ qreal controlX() const;
+ void setControlX(qreal x);
+
+ qreal controlY() const;
+ void setControlY(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+private:
+ qreal _controlX;
+ qreal _controlY;
+};
+QML_DECLARE_TYPE(QFxPathQuad)
+
+class Q_DECLARATIVE_EXPORT QFxPathCubic : public QFxCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY changed)
+ Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY changed)
+ Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY changed)
+ Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY changed)
+public:
+ QFxPathCubic(QObject *parent=0) : QFxCurve(parent), _control1X(0), _control1Y(0), _control2X(0), _control2Y(0) {}
+
+ qreal control1X() const;
+ void setControl1X(qreal x);
+
+ qreal control1Y() const;
+ void setControl1Y(qreal y);
+
+ qreal control2X() const;
+ void setControl2X(qreal x);
+
+ qreal control2Y() const;
+ void setControl2Y(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+private:
+ int _control1X;
+ int _control1Y;
+ int _control2X;
+ int _control2Y;
+};
+QML_DECLARE_TYPE(QFxPathCubic)
+
+class Q_DECLARATIVE_EXPORT QFxPathPercent : public QFxPathElement
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal value READ value WRITE setValue)
+public:
+ QFxPathPercent(QObject *parent=0) : QFxPathElement(parent) {}
+
+ qreal value() const;
+ void setValue(qreal value);
+
+private:
+ qreal _value;
+};
+QML_DECLARE_TYPE(QFxPathPercent)
+
+class QFxPathPrivate;
+class Q_DECLARATIVE_EXPORT QFxPath : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+
+ Q_INTERFACES(QmlParserStatus)
+ Q_PROPERTY(QList<QFxPathElement *>* pathElements READ pathElements)
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX)
+ Q_PROPERTY(qreal startY READ startY WRITE setStartY)
+ Q_CLASSINFO("DefaultProperty", "pathElements")
+ Q_INTERFACES(QmlParserStatus)
+public:
+ QFxPath(QObject *parent=0);
+ ~QFxPath();
+
+ QList<QFxPathElement *>* pathElements();
+
+ qreal startX() const;
+ void setStartX(qreal x);
+
+ qreal startY() const;
+ void setStartY(qreal y);
+
+ QPainterPath path() const;
+ QStringList attributes() const;
+ qreal attributeAt(const QString &, qreal) const;
+ QPointF pointAt(qreal) const;
+
+Q_SIGNALS:
+ void changed();
+
+protected:
+ virtual void componentComplete();
+ QFxPath(QFxPathPrivate &dd, QObject *parent);
+
+private Q_SLOTS:
+ void processPath();
+
+private:
+ struct AttributePoint {
+ AttributePoint() : percent(0), scale(1), origpercent(0) {}
+ AttributePoint(const AttributePoint &other)
+ : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
+ AttributePoint &operator=(const AttributePoint &other) {
+ percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
+ }
+ qreal percent; //massaged percent along the painter path
+ qreal scale;
+ qreal origpercent; //'real' percent along the painter path
+ QHash<QString, qreal> values;
+ };
+
+ void interpolate(int idx, const QString &name, qreal value);
+ void endpoint(const QString &name);
+ void createPointCache() const;
+
+private:
+ Q_DISABLE_COPY(QFxPath)
+ Q_DECLARE_PRIVATE(QFxPath)
+};
+QML_DECLARE_TYPE(QFxPath)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXPATH_H
diff --git a/src/declarative/fx/qfxpath_p.h b/src/declarative/fx/qfxpath_p.h
new file mode 100644
index 0000000..d4a419a
--- /dev/null
+++ b/src/declarative/fx/qfxpath_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATH_P_H
+#define QFXPATH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+#include "qfxpath.h"
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxPathPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QFxPath)
+
+public:
+ QFxPathPrivate() : startX(0), startY(0) { }
+
+ QPainterPath _path;
+ QList<QFxPathElement*> _pathElements;
+ mutable QVector<QPointF> _pointCache;
+ QList<QFxPath::AttributePoint> _attributePoints;
+ QStringList _attributes;
+ int startX;
+ int startY;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp
new file mode 100644
index 0000000..625d778
--- /dev/null
+++ b/src/declarative/fx/qfxpathview.cpp
@@ -0,0 +1,890 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <math.h>
+#include <QDebug>
+#include <QEvent>
+#include "qmlbindablevalue.h"
+#include "qmlstate.h"
+#include "qlistmodelinterface.h"
+#include "qmlopenmetaobject.h"
+
+#include "qfxpathview.h"
+#include "qfxpathview_p.h"
+#include <QGraphicsSceneEvent>
+
+static const int FlickThreshold = 5;
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(QFxPathView,PathView)
+
+class QFxPathViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QFxPathViewAttached(QObject *parent)
+ : QObject(parent), mo(new QmlOpenMetaObject(this))
+ {
+ }
+
+ ~QFxPathViewAttached()
+ {
+ QFxPathView::attachedProperties.remove(parent());
+ }
+
+ QVariant value(const QByteArray &name) const
+ {
+ return mo->value(name);
+ }
+ void setValue(const QByteArray &name, const QVariant &val)
+ {
+ mo->setValue(name, val);
+ }
+
+private:
+ QmlOpenMetaObject *mo;
+};
+
+
+/*!
+ \internal
+ \class QFxPathView
+ \brief The QFxPathView class lays out items provided by a model on a path.
+
+ \ingroup group_views
+
+ The model must be a \l QListModelInterface subclass.
+
+ \sa QFxPath
+*/
+
+/*!
+ \qmlclass PathView
+ \brief The PathView element lays out model-provided items on a path.
+ \inherits Item
+
+ The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML.
+
+ The items are laid out along a path defined by a \l Path and may be flicked to scroll.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
+
+ \image pathview.gif
+
+ \sa Path
+*/
+
+QFxPathView::QFxPathView(QFxItem *parent)
+ : QFxItem(*(new QFxPathViewPrivate), parent)
+{
+ Q_D(QFxPathView);
+ d->init();
+}
+
+QFxPathView::QFxPathView(QFxPathViewPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxPathView);
+ d->init();
+}
+
+QFxPathView::~QFxPathView()
+{
+}
+
+/*!
+ \qmlproperty model PathView::model
+ This property holds the model providing data for the view.
+
+ The model provides a set of data that is used to create the items for the view.
+ For large or dynamic datasets the model is usually provided by a C++ model object.
+ Models can also be created directly in XML, using the ListModel element.
+*/
+
+/*!
+ \property QFxPathView::model
+ \brief the model providing data for the view.
+
+ The model must be either a \l QListModelInterface or
+ \l QFxVisualItemModel subclass.
+*/
+QVariant QFxPathView::model() const
+{
+ Q_D(const QFxPathView);
+ return d->modelVariant;
+}
+
+void QFxPathView::setModel(const QVariant &model)
+{
+ Q_D(QFxPathView);
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ for (int i=0; i<d->items.count(); i++){
+ QFxItem *p = d->items[i];
+ d->model->release(p);
+ }
+ d->items.clear();
+ }
+
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QFxVisualItemModel *vim = 0;
+ if (object && (vim = qobject_cast<QFxVisualItemModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setModel(model);
+ }
+ if (d->model) {
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ }
+ d->firstIndex = 0;
+ d->pathOffset = 0;
+ d->regenerate();
+ d->fixOffset();
+}
+
+/*!
+ \qmlproperty int PathView::count
+ This property holds the number of items in the model.
+*/
+int QFxPathView::count() const
+{
+ Q_D(const QFxPathView);
+ return d->model ? d->model->count() : 0;
+}
+
+/*!
+ \qmlproperty Path PathView::path
+ \default
+ This property holds the path used to lay out the items.
+ For more information see the \l Path documentation.
+*/
+QFxPath *QFxPathView::path() const
+{
+ Q_D(const QFxPathView);
+ return d->path;
+}
+
+void QFxPathView::setPath(QFxPath *path)
+{
+ Q_D(QFxPathView);
+ d->path = path;
+ connect(d->path, SIGNAL(changed()), this, SLOT(refill()));
+ d->regenerate();
+}
+
+/*!
+ \qmlproperty int PathView::currentIndex
+ This property holds the index of the current item.
+*/
+int QFxPathView::currentIndex() const
+{
+ Q_D(const QFxPathView);
+ return d->currentIndex;
+}
+
+void QFxPathView::setCurrentIndex(int idx)
+{
+ Q_D(QFxPathView);
+ if (d->model && d->model->count())
+ idx = qAbs(idx % d->model->count());
+ if (d->model && idx != d->currentIndex) {
+ d->currentIndex = idx;
+ d->snapToCurrent();
+ int itemIndex = (idx - d->firstIndex + d->model->count()) % d->model->count();
+ if (itemIndex < d->items.count())
+ d->items.at(itemIndex)->setFocus(true);
+ emit currentIndexChanged();
+ }
+}
+
+/*!
+ \qmlproperty real PathView::offset
+
+ The offset specifies how far along the path the items are from their initial positions.
+*/
+qreal QFxPathView::offset() const
+{
+ Q_D(const QFxPathView);
+ return d->_offset;
+}
+
+void QFxPathView::setOffset(qreal offset)
+{
+ Q_D(QFxPathView);
+ d->setOffset(offset);
+ d->updateCurrent();
+}
+
+void QFxPathViewPrivate::setOffset(qreal o)
+{
+ Q_Q(QFxPathView);
+ if (_offset != o) {
+ _offset = fmod(o, 100.0);
+ if (_offset < 0)
+ _offset = 100.0 + _offset;
+ q->refill();
+ }
+}
+
+/*!
+ \qmlproperty real PathView::snapPosition
+ This property holds the position (0-100) the current item snaps to.
+*/
+
+/*!
+ \property QFxPathView::snapPosition
+ \brief sets the position (0-100) the current item snaps to.
+
+ This property determines the position the nearest item will snap to.
+*/
+qreal QFxPathView::snapPosition() const
+{
+ Q_D(const QFxPathView);
+ return d->snapPos;
+}
+
+void QFxPathView::setSnapPosition(qreal pos)
+{
+ Q_D(QFxPathView);
+ d->snapPos = pos/100;
+ d->fixOffset();
+}
+
+/*!
+ \qmlproperty real PathView::dragMargin
+ This property holds the maximum distance from the path that initiate mouse dragging.
+
+ By default the path can only be dragged by clicking on an item. If
+ dragMargin is greater than zero, a drag can be initiated by clicking
+ within dragMargin pixels of the path.
+*/
+qreal QFxPathView::dragMargin() const
+{
+ Q_D(const QFxPathView);
+ return d->dragMargin;
+}
+
+void QFxPathView::setDragMargin(qreal dragMargin)
+{
+ Q_D(QFxPathView);
+ d->dragMargin = dragMargin;
+}
+
+/*!
+ \qmlproperty component PathView::delegate
+
+ The delegate provides a template describing what each item in the view should look and act like.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+
+/*!
+ \property QFxPathView::delegate
+ \brief the component to use to render the items.
+
+ The delegate is a component that the view will instantiate and destroy
+ as needed to display the items.
+
+*/
+QmlComponent *QFxPathView::delegate() const
+{
+ Q_D(const QFxPathView);
+ return d->model ? d->model->delegate() : 0;
+}
+
+void QFxPathView::setDelegate(QmlComponent *c)
+{
+ Q_D(QFxPathView);
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setDelegate(c);
+ d->regenerate();
+}
+
+/*!
+ \property QFxPathView::pathItemCount
+ \brief the number of items visible on the path at any one time
+ */
+/*!
+ \qmlproperty int PathView::pathItemCount
+ This property holds the number of items visible on the path at any one time
+*/
+int QFxPathView::pathItemCount() const
+{
+ Q_D(const QFxPathView);
+ return d->pathItems;
+}
+
+void QFxPathView::setPathItemCount(int i)
+{
+ Q_D(QFxPathView);
+ if (i == d->pathItems)
+ return;
+ d->pathItems = i;
+ d->regenerate();
+}
+
+QPointF QFxPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
+{
+ //XXX maybe do recursively at increasing resolution.
+ qreal mindist = 1e10; // big number
+ QPointF nearPoint = path->pointAt(0);
+ qreal nearPc = 0;
+ for (qreal i=1; i < 1000; i++) {
+ QPointF pt = path->pointAt(i/1000.0);
+ QPointF diff = pt - point;
+ qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
+ if (dist < mindist) {
+ nearPoint = pt;
+ nearPc = i;
+ mindist = dist;
+ }
+ }
+
+ if (nearPercent)
+ *nearPercent = nearPc / 10.0;
+
+ return nearPoint;
+}
+
+
+void QFxPathView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxPathView);
+ if (!d->items.count())
+ return;
+ QPointF scenePoint = mapToScene(event->pos());
+ int idx = 0;
+ for (; idx < d->items.count(); ++idx) {
+ QRectF rect = d->items.at(idx)->boundingRect();
+ rect = d->items.at(idx)->mapToScene(rect);
+ if (rect.contains(scenePoint))
+ break;
+ }
+ if (idx == d->items.count() && d->dragMargin == 0.) // didn't click on an item
+ return;
+
+ d->startPoint = d->pointNear(event->pos(), &d->startPc);
+ if (idx == d->items.count()) {
+ qreal distance = qAbs(event->pos().x() - d->startPoint.x()) + qAbs(event->pos().y() - d->startPoint.y());
+ if (distance > d->dragMargin)
+ return;
+ }
+
+ d->stealMouse = false;
+ d->lastElapsed = 0;
+ d->lastDist = 0;
+ d->lastPosTime.start();
+ d->tl.clear();
+}
+
+void QFxPathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxPathView);
+ if (d->lastPosTime.isNull())
+ return;
+
+ if (!d->stealMouse) {
+ QPointF delta = event->pos() - d->startPoint;
+ if (qAbs(delta.x()) > FlickThreshold && qAbs(delta.y()) > FlickThreshold)
+ d->stealMouse = true;
+ }
+
+ if (d->stealMouse) {
+ d->moveReason = QFxPathViewPrivate::Mouse;
+ qreal newPc;
+ d->pointNear(event->pos(), &newPc);
+ qreal diff = newPc - d->startPc;
+ if (diff) {
+ setOffset(d->_offset + diff);
+
+ if (diff > 50)
+ diff -= 100;
+ else if (diff < -50)
+ diff += 100;
+
+ d->lastElapsed = d->lastPosTime.restart();
+ d->lastDist = diff;
+ d->startPc = newPc;
+ }
+ }
+}
+
+void QFxPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+{
+ Q_D(QFxPathView);
+ if (d->lastPosTime.isNull())
+ return;
+
+ qreal elapsed = qreal(d->lastElapsed + d->lastPosTime.elapsed()) / 1000.;
+ qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0;
+ if (d->model && d->model->count() && qAbs(velocity) > 5) {
+ if (velocity > 100)
+ velocity = 100;
+ else if (velocity < -100)
+ velocity = -100;
+ qreal inc = fmod(d->_offset - d->snapPos, 100.0 / d->model->count());
+ qreal dist = qAbs(velocity/2 - fmod(velocity/2, 100.0 / d->model->count()) - inc);
+ d->moveOffset.setValue(d->_offset);
+ d->tl.accel(d->moveOffset, velocity, 10, dist);
+ d->tl.execute(d->fixupOffsetEvent);
+ } else {
+ d->fixOffset();
+ }
+
+ d->lastPosTime = QTime();
+ d->stealMouse = false;
+}
+
+bool QFxPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxPathView);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height()));
+ QFxItem *grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ mouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ mousePressEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ mouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if (grabber && d->stealMouse && !grabber->keepMouseGrab())
+ mouseGrabberItem()->ungrabMouse();
+
+ return d->stealMouse;
+ } else if (!d->lastPosTime.isNull()) {
+ d->lastPosTime = QTime();
+ }
+ return false;
+}
+
+bool QFxPathView::mouseFilter(QGraphicsSceneMouseEvent *e)
+{
+ if (!isVisible())
+ return false;
+
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ {
+ bool ret = sendMouseEvent(e);
+ if (e->type() == QEvent::GraphicsSceneMouseRelease)
+ return ret;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void QFxPathViewPrivate::regenerate()
+{
+ Q_Q(QFxPathView);
+ for (int i=0; i<items.count(); i++){
+ QFxItem *p = items[i];
+ releaseItem(p);
+ }
+ items.clear();
+
+ if (!isValid())
+ return;
+
+ if (firstIndex >= model->count())
+ firstIndex = model->count()-1;
+ if (pathOffset >= model->count())
+ pathOffset = model->count()-1;
+
+ int numItems = pathItems >= 0 ? pathItems : model->count();
+ for (int i=0; i < numItems && i < model->count(); ++i){
+ QFxItem *item = getItem((i + firstIndex) % model->count());
+ if (!item) {
+ qWarning() << "PathView: Cannot create item, index" << (i + firstIndex) % model->count();
+ return;
+ }
+ items.append(item);
+ item->setZ(i);
+ }
+ q->refill();
+}
+
+void QFxPathViewPrivate::updateItem(QFxItem *item, qreal percent)
+{
+ if (QObject *obj = QFxPathView::qmlAttachedProperties(item)) {
+ foreach(const QString &attr, path->attributes())
+ static_cast<QFxPathViewAttached *>(obj)->setValue(attr.toLatin1(), path->attributeAt(attr, percent));
+ }
+ QPointF pf = path->pointAt(percent);
+ item->setX(pf.x() - item->width()*item->scale()/2);
+ item->setY(pf.y() - item->height()*item->scale()/2);
+}
+
+void QFxPathView::refill()
+{
+ Q_D(QFxPathView);
+ if (!d->isValid())
+ return;
+
+ QList<qreal> positions;
+ for (int i=0; i<d->items.count(); i++){
+ qreal percent = i * (100. / d->items.count());
+ percent = percent + d->_offset;
+ percent = fmod(percent,100.);
+ positions << qAbs(percent/100.0);
+ }
+
+ if (d->pathItems==-1) {
+ for (int i=0; i<positions.count(); i++)
+ d->updateItem(d->items.at(i), positions[i]);
+ return;
+ }
+
+ QList<qreal> rotatedPositions;
+ for (int i=0; i<d->items.count(); i++)
+ rotatedPositions << positions[(i + d->pathOffset + d->items.count()) % d->items.count()];
+
+ int wrapIndex= -1;
+ for (int i=0; i<d->items.count()-1; i++) {
+ if (rotatedPositions[i] > rotatedPositions[i+1]){
+ wrapIndex = i;
+ break;
+ }
+ }
+ if (wrapIndex != -1 ){
+ //A wraparound has occured
+ if (wrapIndex < d->items.count()/2){
+ while(wrapIndex-- >= 0){
+ QFxItem* p = d->items.takeFirst();
+ d->updateItem(p, 0.0);
+ d->releaseItem(p);
+ d->firstIndex++;
+ d->firstIndex %= d->model->count();
+ int index = (d->firstIndex + d->items.count())%d->model->count();
+ d->items << d->getItem(index);
+ d->items.last()->setZ(wrapIndex);
+ d->pathOffset++;
+ d->pathOffset=d->pathOffset % d->items.count();
+ }
+ } else {
+ while(wrapIndex++ < d->items.count()-1){
+ QFxItem* p = d->items.takeLast();
+ d->updateItem(p, 1.0);
+ d->releaseItem(p);
+ d->firstIndex--;
+ if (d->firstIndex < 0)
+ d->firstIndex = d->model->count() - 1;
+ d->items.prepend(d->getItem(d->firstIndex));
+ d->items.first()->setZ(d->firstIndex);
+ d->pathOffset--;
+ if (d->pathOffset < 0)
+ d->pathOffset = d->items.count() - 1;
+ }
+ }
+ for (int i=0; i<d->items.count(); i++)
+ rotatedPositions[i] = positions[(i + d->pathOffset + d->items.count())
+ % d->items.count()];
+ }
+ for (int i=0; i<d->items.count(); i++)
+ d->updateItem(d->items.at(i), rotatedPositions[i]);
+}
+
+void QFxPathView::itemsInserted(int modelIndex, int count)
+{
+ //XXX support animated insertion
+ Q_D(QFxPathView);
+ if (!d->isValid())
+ return;
+ if (d->pathItems == -1) {
+ for (int i = 0; i < count; ++i) {
+ QFxItem *item = d->getItem(modelIndex + i);
+ item->setZ(modelIndex + i);
+ d->items.insert(modelIndex + i, item);
+ }
+ refill();
+ } else {
+ //XXX This is pretty heavy handed until we reference count items.
+ d->regenerate();
+ }
+
+ // make sure the current item is still at the snap position
+ int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
+ itemIndex += d->pathOffset;
+ itemIndex %= d->items.count();
+ qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100);
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset != d->_offset)
+ d->moveOffset.setValue(targetOffset);
+}
+
+void QFxPathView::itemsRemoved(int modelIndex, int count)
+{
+ //XXX support animated removal
+ Q_D(QFxPathView);
+ if (!d->isValid())
+ return;
+ if (d->pathItems == -1) {
+ for (int i = 0; i < count; ++i) {
+ QFxItem* p = d->items.takeAt(modelIndex);
+ d->model->release(p);
+ }
+ d->snapToCurrent();
+ refill();
+ } else {
+ d->regenerate();
+ }
+
+ if (d->model->count() == 0) {
+ d->currentIndex = -1;
+ d->moveOffset.setValue(0);
+ return;
+ }
+
+ // make sure the current item is still at the snap position
+ if (d->currentIndex >= d->model->count())
+ d->currentIndex = d->model->count() - 1;
+ int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
+ itemIndex += d->pathOffset;
+ itemIndex %= d->items.count();
+ qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100);
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset != d->_offset)
+ d->moveOffset.setValue(targetOffset);
+}
+
+void QFxPathView::createdItem(int index, QFxItem *item)
+{
+ Q_D(QFxPathView);
+ if (d->requestedIndex != index) {
+ item->setItemParent(this);
+ d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0);
+ }
+}
+
+void QFxPathView::destroyingItem(QFxItem *item)
+{
+ Q_UNUSED(item);
+}
+
+void QFxPathView::ticked()
+{
+ Q_D(QFxPathView);
+ d->updateCurrent();
+}
+
+// find the item closest to the snap position
+int QFxPathViewPrivate::calcCurrentIndex()
+{
+ int current = -1;
+ if (model && items.count()) {
+ _offset = fmod(_offset, 100.0);
+ if (_offset < 0)
+ _offset += 100.0;
+
+ if (pathItems == -1) {
+ qreal delta = fmod(_offset - snapPos, 100.0);
+ if (delta < 0)
+ delta = 100.0 + delta;
+ int ii = model->count() - qRound(delta * model->count() / 100);
+ if (ii < 0)
+ ii = 0;
+ current = ii;
+ } else {
+ qreal bestDiff=1e9;
+ int bestI=-1;
+ for (int i=0; i<items.count(); i++){
+ qreal percent = i * (100. / items.count());
+ percent = percent + _offset;
+ percent = fmod(percent,100.);
+ qreal diff = qAbs(snapPos - (percent/100.0));
+ if (diff < bestDiff){
+ bestDiff = diff;
+ bestI = i;
+ }
+ }
+ int modelIndex = (bestI - pathOffset + items.count())%items.count();
+ modelIndex += firstIndex;
+ current = modelIndex;
+ }
+ current = qAbs(current % model->count());
+ }
+
+ return current;
+}
+
+void QFxPathViewPrivate::updateCurrent()
+{
+ Q_Q(QFxPathView);
+ if (moveReason != Mouse)
+ return;
+ int idx = calcCurrentIndex();
+ if (model && idx != currentIndex) {
+ currentIndex = idx;
+ int itemIndex = (idx - firstIndex + model->count()) % model->count();
+ if (itemIndex < items.count())
+ items.at(itemIndex)->setFocus(true);
+ emit q->currentIndexChanged();
+ }
+}
+
+void QFxPathViewPrivate::fixOffset()
+{
+ Q_Q(QFxPathView);
+ if (model && items.count()) {
+ int curr = calcCurrentIndex();
+ if (curr != currentIndex)
+ q->setCurrentIndex(curr);
+ else
+ snapToCurrent();
+ }
+}
+
+void QFxPathViewPrivate::snapToCurrent()
+{
+ if (!model || model->count() <= 0)
+ return;
+
+ int itemIndex = (currentIndex - firstIndex + model->count()) % model->count();
+
+ //Rounds is the number of times round to make the current item visible
+ int rounds = itemIndex / items.count();
+ int otherWayRounds = (model->count() - (itemIndex)) / items.count() + 1;
+ if (otherWayRounds < rounds)
+ rounds = -otherWayRounds;
+
+ itemIndex += pathOffset;
+ itemIndex %= items.count();
+ qreal targetOffset = fmod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), 100);
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset == _offset && rounds == 0)
+ return;
+
+ moveReason = Other;
+ tl.clear();
+ moveOffset.setValue(_offset);
+
+ if (rounds!=0){
+ //Compensate if the targetOffset would bring the target it from off the screen
+ qreal distance = targetOffset - _offset;
+ if (distance <= -50)
+ rounds--;
+ if (distance > 50)
+ rounds++;
+ tl.move(moveOffset, targetOffset + 100.0*(-rounds), QEasingCurve(QEasingCurve::InOutQuad),
+ int(100*items.count()*qMax((qreal)(2.0/items.count()),(qreal)qAbs(rounds))));
+ tl.execute(fixupOffsetEvent);
+ return;
+ }
+
+ if (targetOffset - _offset > 50.0) {
+ qreal distance = 100 - targetOffset + _offset;
+ tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * _offset / distance));
+ tl.set(moveOffset, 100.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * (100-targetOffset) / distance));
+ } else if (targetOffset - _offset <= -50.0) {
+ qreal distance = 100 - _offset + targetOffset;
+ tl.move(moveOffset, 100.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * (100-_offset) / distance));
+ tl.set(moveOffset, 0.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * targetOffset / distance));
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+}
+
+QHash<QObject*, QObject*> QFxPathView::attachedProperties;
+QObject *QFxPathView::qmlAttachedProperties(QObject *obj)
+{
+ QObject *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QFxPathViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+}
+
+QT_END_NAMESPACE
+
+#include "qfxpathview.moc"
diff --git a/src/declarative/fx/qfxpathview.h b/src/declarative/fx/qfxpathview.h
new file mode 100644
index 0000000..cbdafa8
--- /dev/null
+++ b/src/declarative/fx/qfxpathview.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATHVIEW_H
+#define QFXPATHVIEW_H
+
+#include <QtDeclarative/qfxitem.h>
+#include <QtDeclarative/qfxpath.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QListModelInterface;
+class QFxPathViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxPathView : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QFxPath *path READ path WRITE setPath)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
+ Q_PROPERTY(qreal snapPosition READ snapPosition WRITE setSnapPosition)
+ Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+public:
+ QFxPathView(QFxItem *parent=0);
+ virtual ~QFxPathView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QFxPath *path() const;
+ void setPath(QFxPath *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ qreal offset() const;
+ void setOffset(qreal offset);
+
+ qreal snapPosition() const;
+ void setSnapPosition(qreal pos);
+
+ qreal dragMargin() const;
+ void setDragMargin(qreal margin);
+
+ int count() const;
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int pathItemCount() const;
+ void setPathItemCount(int);
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void currentIndexChanged();
+ void offsetChanged();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+ bool mouseFilter(QGraphicsSceneMouseEvent *e);
+
+private Q_SLOTS:
+ void refill();
+ void ticked();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void createdItem(int index, QFxItem *item);
+ void destroyingItem(QFxItem *item);
+
+protected:
+ QFxPathView(QFxPathViewPrivate &dd, QFxItem *parent);
+
+private:
+ friend class QFxPathViewAttached;
+ static QHash<QObject*, QObject*> attachedProperties;
+ Q_DISABLE_COPY(QFxPathView)
+ Q_DECLARE_PRIVATE(QFxPathView)
+};
+QML_DECLARE_TYPE(QFxPathView)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXPATHVIEW_H
diff --git a/src/declarative/fx/qfxpathview_p.h b/src/declarative/fx/qfxpathview_p.h
new file mode 100644
index 0000000..b5c5ba2
--- /dev/null
+++ b/src/declarative/fx/qfxpathview_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATHVIEW_P_H
+#define QFXPATHVIEW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qdatetime.h"
+#include "qfxpathview.h"
+#include "qfxitem_p.h"
+#include "qfxvisualitemmodel.h"
+#include "qml.h"
+#include "qmltimelinevalueproxy.h"
+#include "private/qmlanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef struct PathViewItem{
+ int index;
+ QFxItem* item;
+}PathViewItem;
+
+class QFxPathViewPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxPathView)
+
+public:
+ QFxPathViewPrivate()
+ : path(0), currentIndex(0), startPc(0), lastDist(0)
+ , lastElapsed(0), stealMouse(false), ownModel(false), activeItem(0)
+ , snapPos(0), dragMargin(0), moveOffset(this, &QFxPathViewPrivate::setOffset)
+ , firstIndex(0), pathItems(-1), pathOffset(0), requestedIndex(-1), model(0)
+ , moveReason(Other)
+ {
+ fixupOffsetEvent = QmlTimeLineEvent::timeLineEvent<QFxPathViewPrivate, &QFxPathViewPrivate::fixOffset>(&moveOffset, this);
+ }
+
+ void init()
+ {
+ Q_Q(QFxPathView);
+ _offset = 0;
+ q->setAcceptedMouseButtons(Qt::NoButton);
+ q->setOptions(QSimpleCanvasItem::MouseFilter | QSimpleCanvasItem::MouseEvents | QSimpleCanvasItem::IsFocusRealm);
+ q->connect(&tl, SIGNAL(updated()), q, SLOT(ticked()));
+ }
+
+ QFxItem *getItem(int modelIndex) {
+ Q_Q(QFxPathView);
+ requestedIndex = modelIndex;
+ QFxItem *item = model->item(modelIndex);
+ if (item)
+ item->setItemParent(q);
+ requestedIndex = -1;
+ return item;
+ }
+ void releaseItem(QFxItem *item) {
+ model->release(item);
+ }
+
+ bool isValid() const {
+ return model && model->count() > 0 && model->delegate() && path;
+ }
+
+ int calcCurrentIndex();
+ void updateCurrent();
+ void fixOffset();
+ void setOffset(qreal offset);
+ void regenerate();
+ void updateItem(QFxItem *, qreal);
+ void snapToCurrent();
+ QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const;
+
+ QFxPath *path;
+ int currentIndex;
+ qreal startPc;
+ QPointF startPoint;
+ qreal lastDist;
+ int lastElapsed;
+ qreal _offset;
+ bool stealMouse : 1;
+ bool ownModel : 1;
+ QTime lastPosTime;
+ QPointF lastPos;
+ QFxItem *activeItem;
+ qreal snapPos;
+ qreal dragMargin;
+ QmlTimeLine tl;
+ QmlTimeLineValueProxy<QFxPathViewPrivate> moveOffset;
+ QmlTimeLineEvent fixupOffsetEvent;
+ int firstIndex;
+ int pathItems;
+ int pathOffset;
+ int requestedIndex;
+ QList<QFxItem *> items;
+ QFxVisualItemModel *model;
+ QVariant modelVariant;
+ enum MovementReason { Other, Key, Mouse };
+ MovementReason moveReason;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/fx/qfxpixmap.cpp b/src/declarative/fx/qfxpixmap.cpp
new file mode 100644
index 0000000..0ea94f5
--- /dev/null
+++ b/src/declarative/fx/qfxpixmap.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxpixmap.h"
+#include <QHash>
+#include <QNetworkReply>
+#include <QPixmapCache>
+#include <qfxperf.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+class QSharedNetworkReply;
+typedef QHash<QString, QSharedNetworkReply *> QFxSharedNetworkReplyHash;
+static QFxSharedNetworkReplyHash qfxActiveNetworkReplies;
+
+class QSharedNetworkReply
+{
+public:
+ QSharedNetworkReply(QNetworkReply *r) : reply(r), refCount(1) {}
+ ~QSharedNetworkReply()
+ {
+ reply->deleteLater();
+ }
+ QNetworkReply *reply;
+
+ int refCount;
+ void addRef()
+ {
+ ++refCount;
+ }
+ void release()
+ {
+ Q_ASSERT(refCount > 0);
+ --refCount;
+ if (refCount == 0) {
+ QString key = reply->url().toString();
+ qfxActiveNetworkReplies.remove(key);
+ delete this;
+ }
+ }
+};
+
+class QFxPixmapPrivate
+{
+public:
+ QFxPixmapPrivate() {}
+
+ QPixmap pixmap;
+};
+
+/*!
+ \internal
+ \class QFxPixmap
+ \ingroup group_utility
+ \brief Enacapsultes a pixmap for QFx items.
+
+ This class is NOT reentrant.
+ The pixmap cache will grow indefinately.
+ */
+QFxPixmap::QFxPixmap()
+: d(new QFxPixmapPrivate)
+{
+}
+
+QFxPixmap::QFxPixmap(const QUrl &url)
+: d(new QFxPixmapPrivate)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::PixmapLoad> perf;
+#endif
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ if (url.scheme()==QLatin1String("file")) {
+ d->pixmap.load(url.toLocalFile());
+ } else
+#endif
+ {
+ QString key = url.toString();
+ if (!QPixmapCache::find(key,&d->pixmap)) {
+ QFxSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key);
+ if (iter == qfxActiveNetworkReplies.end()) {
+ // API usage error
+ qWarning() << "QFxPixmap: URL not loaded" << url;
+ } else {
+ if ((*iter)->reply->error()) {
+ qWarning() << "Network error loading" << url << (*iter)->reply->errorString();
+ } else {
+ QImage img;
+ if (img.load((*iter)->reply, 0)) {
+ d->pixmap = QPixmap::fromImage(img);
+ QPixmapCache::insert(key, d->pixmap);
+ } else {
+ qWarning() << "Format error loading" << url;
+ }
+ }
+ (*iter)->release();
+ }
+ }
+ }
+}
+
+QFxPixmap::QFxPixmap(const QFxPixmap &o)
+: d(new QFxPixmapPrivate)
+{
+ d->pixmap = o.d->pixmap;
+}
+
+QFxPixmap::~QFxPixmap()
+{
+ delete d;
+}
+
+QFxPixmap &QFxPixmap::operator=(const QFxPixmap &o)
+{
+ d->pixmap = o.d->pixmap;
+ return *this;
+}
+
+bool QFxPixmap::isNull() const
+{
+ return d->pixmap.isNull();
+}
+
+int QFxPixmap::width() const
+{
+ return d->pixmap.width();
+}
+
+int QFxPixmap::height() const
+{
+ return d->pixmap.height();
+}
+
+QFxPixmap::operator const QPixmap &() const
+{
+ return d->pixmap;
+}
+
+/*!
+ Starts a network request to load \a url. When the URL is loaded,
+ the given slot is invoked. Note that if the image is already cached,
+ the slot may be invoked immediately.
+
+ Returns a QNetworkReply if the image is not immediately available, otherwise
+ returns 0. The QNetworkReply must not be stored - it may be destroyed at any time.
+*/
+QNetworkReply *QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char* slot)
+{
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ if (url.scheme()==QLatin1String("file")) {
+ QObject dummy;
+ QObject::connect(&dummy, SIGNAL(destroyed()), obj, slot);
+ return 0;
+ }
+#endif
+
+ QString key = url.toString();
+ if (QPixmapCache::find(key,0)) {
+ QObject dummy;
+ QObject::connect(&dummy, SIGNAL(destroyed()), obj, slot);
+ return 0;
+ }
+
+ QFxSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key);
+ if (iter == qfxActiveNetworkReplies.end()) {
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ QSharedNetworkReply *item = new QSharedNetworkReply(engine->networkAccessManager()->get(req));
+ iter = qfxActiveNetworkReplies.insert(key, item);
+ } else {
+ (*iter)->addRef();
+ }
+
+ QObject::connect((*iter)->reply, SIGNAL(finished()), obj, slot);
+ return (*iter)->reply;
+}
+
+/*!
+ Stops the given slot being invoked if the given url finishes loading.
+ May also cancel loading (eg. if no other pending request).
+
+ Any connections to the QNetworkReply returned by get() will be
+ disconnected.
+*/
+void QFxPixmap::cancelGet(const QUrl& url, QObject* obj)
+{
+ QString key = url.toString();
+ QFxSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key);
+ if (iter == qfxActiveNetworkReplies.end())
+ return;
+ QObject::disconnect((*iter)->reply, 0, obj, 0);
+ (*iter)->release();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpixmap.h b/src/declarative/fx/qfxpixmap.h
new file mode 100644
index 0000000..ae693c1
--- /dev/null
+++ b/src/declarative/fx/qfxpixmap.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPIXMAP_H
+#define QFXPIXMAP_H
+
+#include <QtCore/QString>
+#include <QtGui/QPixmap>
+#include <QtDeclarative/qsimplecanvas.h>
+#include <QtDeclarative/qfxglobal.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlEngine;
+class QNetworkReply;
+class QFxPixmapPrivate;
+class Q_DECLARATIVE_EXPORT QFxPixmap
+{
+public:
+ QFxPixmap();
+ QFxPixmap(const QUrl& url); // url must have been passed to QFxPixmap::get, and finished.
+ QFxPixmap(const QFxPixmap &);
+ virtual ~QFxPixmap();
+
+ QFxPixmap &operator=(const QFxPixmap &);
+
+ static QNetworkReply *get(QmlEngine *, const QUrl& url, QObject*, const char* slot);
+ static void cancelGet(const QUrl& url, QObject* obj);
+
+ bool isNull() const;
+
+ int width() const;
+ int height() const;
+
+ operator const QPixmap &() const;
+
+private:
+ QFxPixmapPrivate *d;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXPIXMAP_H
diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp
new file mode 100644
index 0000000..c156753
--- /dev/null
+++ b/src/declarative/fx/qfxrect.cpp
@@ -0,0 +1,1005 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxrect.h"
+#include "qfxrect_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxPen,Pen)
+QML_DEFINE_TYPE(QFxGradientStop,GradientStop)
+QML_DEFINE_TYPE(QFxGradient,Gradient)
+
+/*!
+ \internal
+ \class QFxPen
+ \ingroup group_utility
+ \brief The QFxPen class provides a pen used for drawing rect borders on a QFxView.
+
+ By default, the pen is invalid and nothing is drawn. You must either set a color (then the default
+ width is 0) or a width (then the default color is black).
+
+ A width of 0 indicates a cosmetic pen, a single-pixel line on the border of the item being painted.
+
+ Example:
+ \qml
+ Rect { pen.width: 2; pen.color: "red" ... }
+ \endqml
+*/
+
+/*! \property QFxPen::width
+ \brief the width of the pen.
+
+ A width of 0 is a single-pixel line on the border of the item being painted.
+
+ If the width is less than 0 the pen is considered invalid and won't be used.
+*/
+
+/*!
+ \property QFxPen::color
+ \brief the color of the pen.
+
+ color is most commonly specified in hexidecimal notation (#RRGGBB)
+ or as an \l {http://www.w3.org/TR/SVG/types.html#ColorKeywords}{SVG color keyword name}
+ (as defined by the World Wide Web Consortium). For example:
+ \qml
+ // rect with green border using hexidecimal notation
+ Rect { pen.color: "#00FF00" }
+
+ // rect with steelblue border using SVG color name
+ Rect { pen.color: "steelblue" }
+ \endqml
+
+ For the full set of ways to specify color, see Qt's QColor::setNamedColor documentation.
+*/
+
+void QFxPen::setColor(const QColor &c)
+{
+ _color = c;
+ _valid = _color.alpha() ? true : false;
+ emit updated();
+}
+
+/*!
+ \property QFxPen::width
+ \brief the width of the pen.
+
+ \qml
+ // rect with green border using hexidecimal notation
+ Rect { pen.width: 4 }
+ \endqml
+
+ A width of 0 creates a thin line. For no line, use a negative width or a transparent color.
+
+ Odd pen widths generally lead to half-pixel painting.
+*/
+void QFxPen::setWidth(int w)
+{
+ _width = w;
+ _valid = (_width < 0) ? false : true;
+ emit updated();
+}
+
+
+/*!
+ \qmlclass GradientStop QFxGradientStop
+ \brief The GradientStop item defines the color at a position in a Gradient
+
+ \sa Gradient
+*/
+
+/*!
+ \qmlproperty real GradientStop::position
+ \qmlproperty color GradientStop::color
+
+ Sets a \e color at a \e position in a gradient.
+*/
+
+void QFxGradientStop::updateGradient()
+{
+ if (QFxGradient *grad = qobject_cast<QFxGradient*>(parent()))
+ grad->doUpdate();
+}
+
+/*!
+ \qmlclass Gradient QFxGradient
+ \brief The Gradient item defines a gradient fill.
+
+ A gradient is defined by two or more colors, which will be blended seemlessly. The
+ colors are specified at their position in the range 0.0 - 1.0 via
+ the GradientStop item. For example, the following code paints a
+ Rect with a gradient starting with red, blending to yellow at 1/3 of the
+ size of the Rect, and ending with Green:
+
+ \table
+ \row
+ \o \image gradient.png
+ \o \quotefile doc/src/snippets/declarative/gradient.qml
+ \endtable
+
+ \sa GradientStop
+*/
+
+/*!
+ \qmlproperty list<GradientStop> Gradient::stops
+ This property holds the gradient stops describing the gradient.
+*/
+
+const QGradient *QFxGradient::gradient() const
+{
+ if (!m_gradient && !m_stops.isEmpty()) {
+ m_gradient = new QLinearGradient(0,0,0,1.0);
+ for (int i = 0; i < m_stops.count(); ++i) {
+ const QFxGradientStop *stop = m_stops.at(i);
+ m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_gradient->setColorAt(stop->position(), stop->color());
+ }
+ }
+
+ return m_gradient;
+}
+
+void QFxGradient::doUpdate()
+{
+ delete m_gradient;
+ m_gradient = 0;
+ emit updated();
+}
+
+QML_DEFINE_TYPE(QFxRect,Rect)
+
+/*!
+ \qmlclass Rect QFxRect
+ \brief The Rect item allows you to add rectangles to a scene.
+ \inherits Item
+
+ A Rect is painted having a solid fill (color) and an optional border (pen).
+ You can also create rounded rectangles using the radius property.
+
+ \qml
+ Rect {
+ width: 100
+ height: 100
+ color: "red"
+ pen.color: "black"
+ pen.width: 5
+ radius: 10
+ }
+ \endqml
+
+ \image declarative-rect.png
+*/
+
+/*!
+ \internal
+ \class QFxRect
+ \brief The QFxRect class provides a rect item that you can add to a QFxView.
+
+ A Rect is painted having a solid fill (color) and an optional border (pen).
+ You can also create rounded rectangles using the radius property.
+
+ \qml
+ Rect {
+ width: 100
+ height: 100
+ color: "red"
+ pen.color: "black"
+ pen.width: 5
+ radius: 10
+ }
+ \endqml
+
+ \image declarative-rect.png
+
+ A QFxRect object can be instantiated in Qml using the tag \l Rect.
+
+ \ingroup group_coreitems
+*/
+QFxRect::QFxRect(QFxItem *parent)
+ : QFxItem(*(new QFxRectPrivate), parent)
+{
+ Q_D(QFxRect);
+ d->init();
+ setOptions(HasContents, true);
+}
+
+QFxRect::QFxRect(QFxRectPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxRect);
+ d->init();
+ setOptions(HasContents, true);
+}
+
+void QFxRect::doUpdate()
+{
+#if defined(QFX_RENDER_QPAINTER)
+ Q_D(QFxRect);
+ d->_rectImage = QPixmap();
+#endif
+#if defined(QFX_RENDER_OPENGL)
+ Q_D(QFxRect);
+ d->_rectTexture.clear();
+#endif
+ const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0;
+ setPaintMargin((pw+1)/2);
+ update();
+}
+
+/*!
+ \qmlproperty int Rect::pen.width
+ \qmlproperty color Rect::pen.color
+
+ The pen used to draw the border of the rect.
+*/
+/*!
+ \property QFxRect::pen
+ \brief the pen used to draw the border of the rect.
+*/
+QFxPen *QFxRect::pen()
+{
+ Q_D(QFxRect);
+ return d->pen();
+}
+
+/*!
+ \qmlproperty Gradient Rect::gradient
+
+ The gradient to use to fill the rect.
+
+ This property allows for the construction of simple vertical gradients.
+ Other gradients may by formed by adding rotation to the rect.
+
+ \table
+ \row
+ \o \image declarative-rect_gradient.png
+ \o
+ \qml
+ Rect { y: 0; width: 80; height: 80; color: "lightsteelblue" }
+ Rect { y: 100; width: 80; height: 80
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightsteelblue" }
+ GradientStop { position: 1.0; color: "blue" }
+ }
+ }
+ Rect { rotation: 90; x: 80; y: 200; width: 80; height: 80
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightsteelblue" }
+ GradientStop { position: 1.0; color: "blue" }
+ }
+ }
+ // The x offset is needed because the rotation is from the top left corner
+ \endqml
+ \endtable
+
+ \sa Gradient, color
+*/
+QFxGradient *QFxRect::gradient() const
+{
+ Q_D(const QFxRect);
+ return d->gradient;
+}
+
+void QFxRect::setGradient(QFxGradient *gradient)
+{
+ Q_D(QFxRect);
+ if (d->gradient == gradient)
+ return;
+ if (d->gradient)
+ disconnect(d->gradient, SIGNAL(updated()), this, SLOT(doUpdate()));
+ d->gradient = gradient;
+ if (d->gradient)
+ connect(d->gradient, SIGNAL(updated()), this, SLOT(doUpdate()));
+ update();
+}
+
+
+/*!
+ \qmlproperty real Rect::radius
+ This property holds the corner radius used to draw a rounded rect.
+
+ If radius is non-zero, the rect will be painted as a rounded rectangle, otherwise it will be
+ painted as a normal rectangle. The same radius is used by all 4 corners; there is currently
+ no way to specify different radii for different corners.
+*/
+
+/*!
+ \property QFxRect::radius
+ \brief the corner radius used to draw a rounded rect.
+*/
+qreal QFxRect::radius() const
+{
+ Q_D(const QFxRect);
+ return d->_radius;
+}
+
+void QFxRect::setRadius(qreal radius)
+{
+ Q_D(QFxRect);
+ if (d->_radius == radius)
+ return;
+
+ d->_radius = radius;
+#if defined(QFX_RENDER_QPAINTER)
+ d->_rectImage = QPixmap();
+#elif defined(QFX_RENDER_OPENGL)
+ d->_rectTexture.clear();
+#endif
+ update();
+}
+
+void QFxRect::dump(int depth)
+{
+ Q_D(QFxRect);
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "QFxRect:" << d->_color;
+ QFxItem::dump(depth);
+}
+
+/*!
+ \qmlproperty color Rect::color
+ This property holds the color used to fill the rect.
+
+ \qml
+ // green rect using hexidecimal notation
+ Rect { color: "#00FF00" }
+
+ // steelblue rect using SVG color name
+ Rect { color: "steelblue" }
+ \endqml
+*/
+
+/*!
+ \property QFxRect::color
+ \brief the color used to fill the rect.
+*/
+QColor QFxRect::color() const
+{
+ Q_D(const QFxRect);
+ return d->_color;
+}
+
+void QFxRect::setColor(const QColor &c)
+{
+ Q_D(QFxRect);
+ if (d->_color == c)
+ return;
+
+ d->_color = c;
+#if defined(QFX_RENDER_QPAINTER)
+ d->_rectImage = QPixmap();
+#endif
+#if defined(QFX_RENDER_OPENGL)
+ d->_rectTexture.clear();
+#endif
+ update();
+}
+
+
+
+/*!
+ \qmlproperty color Rect::tintColor
+ This property holds The color to tint the rectangle.
+
+ This color will be drawn over the rect's color when the rect is painted. The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque.
+
+ \qml
+ Rect { x: 0; width: 80; height: 80; color: "lightsteelblue" }
+ Rect { x: 100; width: 80; height: 80; color: "lightsteelblue"; tintColor: "#10FF0000" }
+ \endqml
+ \image declarative-rect_tint.png
+
+ This attribute is not intended to be used with a single color over the lifetime of an user interface. It is most useful when a subtle change is intended to be conveyed due to some event; you can then use the tint color to more effectively tune the visible color.
+*/
+
+/*!
+ \property QFxRect::tintColor
+ \brief The color to tint the rectangle.
+*/
+QColor QFxRect::tintColor() const
+{
+ Q_D(const QFxRect);
+ return d->_tintColor;
+}
+
+void QFxRect::setTintColor(const QColor &c)
+{
+ Q_D(QFxRect);
+ if (d->_tintColor == c)
+ return;
+
+ d->_tintColor = c;
+ update();
+}
+
+QColor QFxRectPrivate::getColor()
+{
+ if (_tintColor.isValid()) {
+ int a = _tintColor.alpha();
+ if (a == 0xFF)
+ return _tintColor;
+ else if (a == 0x00)
+ return _color;
+ else {
+ uint src = _tintColor.rgba();
+ uint dest = _color.rgba();
+
+ uint res = (((a * (src & 0xFF00FF)) +
+ ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF;
+ res |= (((a * ((src >> 8) & 0xFF00FF)) +
+ ((0xFF - a) * ((dest >> 8) & 0xFF00FF)))) & 0xFF00FF00;
+ if ((src & 0xFF000000) == 0xFF000000)
+ res |= 0xFF000000;
+
+ return QColor::fromRgba(res);
+ }
+ } else {
+ return _color;
+ }
+}
+
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxRect::generateRoundedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectImage.isNull()) {
+ const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0;
+ d->_rectImage = QPixmap(d->_radius*2 + 3 + pw*2, d->_radius*2 + 3 + pw*2);
+ d->_rectImage.fill(Qt::transparent);
+ QPainter p(&(d->_rectImage));
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->_pen && d->_pen->isValid()) {
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->_color);
+ p.drawRoundedRect((pw+1)/2, (pw+1)/2, d->_rectImage.width()-(pw+1)/2*2, d->_rectImage.height()-(pw+1)/2*2, d->_radius, d->_radius);
+ }
+}
+
+void QFxRect::generateBorderedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectImage.isNull()) {
+ const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0;
+ d->_rectImage = QPixmap(d->pen()->width()*2 + 3 + pw*2, d->pen()->width()*2 + 3 + pw*2);
+ d->_rectImage.fill(Qt::transparent);
+ QPainter p(&(d->_rectImage));
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->_pen && d->_pen->isValid()) {
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->_color);
+ p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, d->_rectImage.width()-(pw+1)/2*2, d->_rectImage.height()-(pw+1)/2*2);
+ }
+}
+#elif defined(QFX_RENDER_OPENGL)
+void QFxRect::generateRoundedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectTexture.isNull()) {
+ const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0;
+ QImage roundRect(d->_radius*2 + 4 + pw*2, d->_radius*2 + 4 + pw*2, QImage::Format_ARGB32_Premultiplied);
+ roundRect.fill(0);
+ QPainter p(&roundRect);
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->_pen && d->_pen->isValid()) {
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->_color);
+ p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->_radius, d->_radius);
+ d->_rectTexture.setImage(roundRect);
+ }
+}
+
+void QFxRect::generateBorderedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectTexture.isNull()) {
+ const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0;
+ QImage borderedRect(pw*2 + 4, pw*2 + 4, QImage::Format_ARGB32_Premultiplied);
+ borderedRect.fill(0);
+ QPainter p(&(borderedRect));
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->_pen && d->_pen->isValid()) {
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->_color);
+ p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2);
+ d->_rectTexture.setImage(borderedRect);
+ }
+}
+#endif
+
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxRect::paintContents(QPainter &p)
+{
+ Q_D(QFxRect);
+ if (d->_radius > 0 || (d->_pen && d->_pen->isValid())
+ || (d->gradient && d->gradient->gradient()) )
+ drawRect(p);
+ else
+ p.fillRect(QRect(0, 0, width(), height()), d->getColor());
+}
+
+void QFxRect::drawRect(QPainter &p)
+{
+ Q_D(QFxRect);
+ if (d->gradient && d->gradient->gradient() /*|| p.usingQt() */) {
+ // XXX This path is still slower than the image path
+ // Image path won't work for gradients though
+ QPainter::RenderHints oldHints = p.renderHints();
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->_pen && d->_pen->isValid()) {
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(*d->gradient->gradient());
+ if (d->_radius > 0.)
+ p.drawRoundedRect(0, 0, width(), height(), d->_radius, d->_radius);
+ else
+ p.drawRect(0, 0, width(), height());
+ p.setRenderHints(oldHints);
+ } else {
+ int offset = 0;
+ const int pw = d->_pen && d->_pen->isValid() ? (d->_pen->width()+1)/2*2 : 0;
+
+ if (d->_radius > 0) {
+ generateRoundedRect();
+ //### implicit conversion to int
+ offset = int(d->_radius+1.5+pw);
+ } else {
+ generateBorderedRect();
+ offset = pw+1;
+ }
+
+ //basically same code as QFxImage uses to paint sci images
+ int w = width()+pw;
+ int h = height()+pw;
+ int xOffset = offset;
+ int xSide = xOffset * 2;
+ bool xMiddles=true;
+ if (xSide > w) {
+ xMiddles=false;
+ xOffset = w/2 + 1;
+ xSide = xOffset * 2;
+ }
+ int yOffset = offset;
+ int ySide = yOffset * 2;
+ bool yMiddles=true;
+ if (ySide > h) {
+ yMiddles = false;
+ yOffset = h/2 + 1;
+ ySide = yOffset * 2;
+ }
+
+ // Upper left
+ p.drawPixmap(QRect(-pw/2, -pw/2, xOffset, yOffset), d->_rectImage, QRect(0, 0, xOffset, yOffset));
+
+ // Upper middle
+ if (xMiddles)
+ p.drawPixmap(QRect(xOffset-pw/2, -pw/2, width() - xSide + pw, yOffset), d->_rectImage,
+ QRect(d->_rectImage.width()/2, 0, 1, yOffset));
+ // Upper right
+ p.drawPixmap(QPoint(width()-xOffset+pw/2, -pw/2), d->_rectImage,
+ QRect(d->_rectImage.width()-xOffset, 0, xOffset, yOffset));
+ // Middle left
+ if (yMiddles)
+ p.drawPixmap(QRect(-pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->_rectImage,
+ QRect(0, d->_rectImage.height()/2, xOffset, 1));
+
+ // Middle
+ if (xMiddles && yMiddles)
+ // XXX paint errors in animation example
+ //p.fillRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw, d->getColor());
+ p.drawPixmap(QRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw), d->_rectImage,
+ QRect(d->_rectImage.width()/2, d->_rectImage.height()/2, 1, 1));
+ // Middle right
+ if (yMiddles)
+ p.drawPixmap(QRect(width()-xOffset+pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->_rectImage,
+ QRect(d->_rectImage.width()-xOffset, d->_rectImage.height()/2, xOffset, 1));
+ // Lower left
+ p.drawPixmap(QPoint(-pw/2, height() - yOffset + pw/2), d->_rectImage, QRect(0, d->_rectImage.height() - yOffset, xOffset, yOffset));
+
+ // Lower Middle
+ if (xMiddles)
+ p.drawPixmap(QRect(xOffset-pw/2, height() - yOffset +pw/2, width() - xSide + pw, yOffset), d->_rectImage,
+ QRect(d->_rectImage.width()/2, d->_rectImage.height() - yOffset, 1, yOffset));
+ // Lower Right
+ p.drawPixmap(QPoint(width()-xOffset+pw/2, height() - yOffset+pw/2), d->_rectImage,
+ QRect(d->_rectImage.width()-xOffset, d->_rectImage.height() - yOffset, xOffset, yOffset));
+ }
+}
+#endif
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+
+void QFxRect::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxRect);
+ if (d->_radius == 0 && (!d->_pen || !d->_pen->isValid())) {
+ if (d->gradient) {
+ float widthV = width();
+ float heightV = height();
+
+ GLfloat vertices[] = { 0, heightV,
+ widthV, heightV,
+ 0, 0,
+ widthV, 0 };
+
+ int count = d->gradient->stops()->size();
+ GLfloat colors[count*8];
+ for (int i = 0; i < count; i += 8) {
+ QFxGradientStop *g = d->gradient->stops()->at(i);
+ QColor c = g->color();
+ colors[i] = c.redF(); colors[i+4] = colors[i];
+ colors[i+1] = c.greenF(); colors[i+5] = colors[i+1];
+ colors[i+2] = c.blueF(); colors[i+6] = colors[i+2];
+ colors[i+3] = c.alphaF() * p.activeOpacity; colors[i+7] = colors[i+3];
+ }
+
+ ColorShader *shader = basicShaders()->color();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+
+ shader->setAttributeArray(ColorShader::Vertices, vertices, 2);
+ shader->setAttributeArray(ColorShader::Colors, colors, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, count*2);
+ shader->disableAttributeArray(ColorShader::Vertices);
+ shader->disableAttributeArray(ColorShader::Colors);
+ } else {
+ QGLShaderProgram *shader = p.useColorShader(d->getColor());
+
+ float widthV = width();
+ float heightV = height();
+
+ GLfloat vertices[] = { 0, heightV,
+ widthV, heightV,
+ 0, 0,
+ widthV, 0 };
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+ }
+ } else {
+ qreal offset = 0;
+ qreal pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0.0;
+
+ if (d->_radius > 0) {
+ generateRoundedRect();
+ offset = d->_radius + pw+1.5;
+ } else {
+ generateBorderedRect();
+ offset = pw+1.5;
+ }
+
+ QGLShaderProgram *shader = p.useTextureShader();
+
+ float texWidth = d->_rectTexture.width();
+ float texHeight = d->_rectTexture.height();
+ if (!texWidth || !texHeight)
+ return;
+
+ float widthV = qreal(width())+pw/2;
+ float heightV = qreal(height())+pw/2;
+
+ float xOffset = offset;
+ bool xMiddles = true;
+ if (xOffset*2 > width()+pw) {
+ xMiddles = false;
+ xOffset = (width()+pw)/2;
+ }
+ float yOffset = offset;
+ bool yMiddles = true;
+ if (yOffset*2 > height()+pw) {
+ yMiddles = false;
+ yOffset = (height()+pw)/2;
+ }
+
+ float texleft = xOffset / texWidth;
+ float imgleft = xOffset-pw/2;
+ float texright = (texWidth-xOffset) / texWidth;
+ float imgright = widthV - xOffset;
+
+ float textop = yOffset / texHeight;
+ float imgtop = yOffset-pw/2;
+ float texbottom = (texHeight-yOffset) / texHeight;
+ float imgbottom = heightV - yOffset;
+
+ //Bug 231768: Inappropriate interpolation was occuring on 3x3 textures
+ if (offset==1)
+ texleft=texright=textop=texbottom=0.5;
+
+ float vert1[] = { -pw/2, -pw/2,
+ -pw/2, imgtop,
+ imgleft, -pw/2,
+ imgleft, imgtop,
+ imgright, -pw/2,
+ imgright, imgtop,
+ widthV, -pw/2,
+ widthV, imgtop };
+ float tex1[] = { 0, 0,
+ 0, textop,
+ texleft, 0,
+ texleft, textop,
+ texright, 0,
+ texright, textop,
+ 1, 0,
+ 1, textop };
+ float vert2[] = { -pw/2, imgtop,
+ -pw/2, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { -pw/2, heightV,
+ -pw/2, imgbottom,
+ imgleft, heightV,
+ imgleft, imgbottom,
+ imgright, heightV,
+ imgright, imgbottom,
+ widthV, heightV,
+ widthV, imgbottom };
+ float tex3[] = { 0, 1,
+ 0, texbottom,
+ texleft, 1,
+ texleft, texbottom,
+ texright, 1,
+ texright, texbottom,
+ 1, 1,
+ 1, texbottom };
+
+ glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture());
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ if (yMiddles) {
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ }
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ }
+}
+#elif defined(QFX_RENDER_OPENGL1)
+void QFxRect::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxRect);
+
+ float widthV = width();
+ float heightV = height();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(p.activeTransform.data());
+
+ if (d->_radius == 0 && (!d->_pen || !d->_pen->isValid())) {
+ GLfloat vertices[] = { 0, heightV,
+ widthV, heightV,
+ 0, 0,
+ widthV, 0 };
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2,GL_FLOAT,0,vertices);
+
+ QColor c;
+ if (d->_gradcolor.isValid())
+ c = d->_color;
+ else
+ c = d->getColor();
+ float r = c.redF();
+ float g = c.greenF();
+ float b = c.blueF();
+ float a = c.alphaF() * p.activeOpacity;
+
+ float r2 = r; float g2 = g; float b2 = b; float a2 = a;
+
+ if (d->_gradcolor.isValid()) {
+ r2 = d->_gradcolor.redF();
+ g2 = d->_gradcolor.greenF();
+ b2 = d->_gradcolor.blueF();
+ a2 = d->_gradcolor.alphaF() * p.activeOpacity;
+ }
+
+ GLfloat colors[] = { r2, g2, b2, a2,
+ r2, g2, b2, a2,
+ r, g, b, a,
+ r, g, b, a };
+
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(4,GL_FLOAT,0,colors);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ } else {
+ qreal offset = 0;
+ if (d->_radius > 0) {
+ generateRoundedRect();
+ offset = d->_radius;
+ } else {
+ generateBorderedRect();
+ offset = d->pen()->width();
+ }
+
+ if (p.activeOpacity == 1.) {
+ GLint i = GL_REPLACE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ } else {
+ GLint i = GL_MODULATE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ glColor4f(1, 1, 1, p.activeOpacity);
+ }
+
+ float texWidth = d->_rectTexture.width();
+ float texHeight = d->_rectTexture.height();
+ if (!texWidth || !texHeight)
+ return;
+
+ float widthV = width();
+ float heightV = height();
+
+ float texleft = 0;
+ float texright = 1;
+ float textop = 1;
+ float texbottom = 0;
+ float imgleft = 0;
+ float imgright = widthV;
+ float imgtop = 0;
+ float imgbottom = heightV;
+
+ texleft = float(offset) / texWidth;
+ imgleft = offset;
+ texright = 1. - float(offset) / texWidth;
+ imgright = widthV - offset;
+ textop = 1. - float(offset) / texHeight;
+ imgtop = offset;
+ texbottom = float(offset) / texHeight;
+ imgbottom = heightV - offset;
+
+ float vert1[] = { 0, 0,
+ 0, imgtop,
+ imgleft, 0,
+ imgleft, imgtop,
+ imgright, 0,
+ imgright, imgtop,
+ widthV, 0,
+ widthV, imgtop };
+ float tex1[] = { 0, 1,
+ 0, textop,
+ texleft, 1,
+ texleft, textop,
+ texright, 1,
+ texright, textop,
+ 1, 1,
+ 1, textop };
+ float vert2[] = { 0, imgtop,
+ 0, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { 0, imgbottom,
+ 0, heightV,
+ imgleft, imgbottom,
+ imgleft, heightV,
+ imgright, imgbottom,
+ imgright, heightV,
+ widthV, imgbottom,
+ widthV, heightV };
+ float tex3[] = { 0, texbottom,
+ 0, 0,
+ texleft, texbottom,
+ texleft, 0,
+ texright, texbottom,
+ texright, 0,
+ 1, texbottom,
+ 1, 0 };
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert1);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert2);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert3);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex3);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+ }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxrect.h b/src/declarative/fx/qfxrect.h
new file mode 100644
index 0000000..c279a1c
--- /dev/null
+++ b/src/declarative/fx/qfxrect.h
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXRECT_H
+#define QFXRECT_H
+
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxPen : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int width READ width WRITE setWidth)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+public:
+ QFxPen(QObject *parent=0)
+ : QObject(parent), _width(0), _color("#000000"), _valid(false)
+ {}
+
+ int width() const { return _width; }
+ void setWidth(int w);
+
+ QColor color() const { return _color; }
+ void setColor(const QColor &c);
+
+ bool isValid() { return _valid; };
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ int _width;
+ QColor _color;
+ bool _valid;
+};
+QML_DECLARE_TYPE(QFxPen)
+
+class Q_DECLARATIVE_EXPORT QFxGradientStop : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal position READ position WRITE setPosition)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+
+public:
+ QFxGradientStop(QObject *parent=0) : QObject(parent) {}
+
+ qreal position() const { return m_position; }
+ void setPosition(qreal position) { m_position = position; updateGradient(); }
+
+ QColor color() const { return m_color; }
+ void setColor(const QColor &color) { m_color = color; updateGradient(); }
+
+private:
+ void updateGradient();
+
+private:
+ qreal m_position;
+ QColor m_color;
+};
+QML_DECLARE_TYPE(QFxGradientStop)
+
+class Q_DECLARATIVE_EXPORT QFxGradient : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QList<QFxGradientStop *> *stops READ stops)
+ Q_CLASSINFO("DefaultProperty", "stops")
+
+public:
+ QFxGradient(QObject *parent=0) : QObject(parent), m_gradient(0) {}
+ ~QFxGradient() { delete m_gradient; }
+
+ QList<QFxGradientStop *> *stops() { return &m_stops; }
+
+ const QGradient *gradient() const;
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ void doUpdate();
+
+private:
+ QList<QFxGradientStop *> m_stops;
+ mutable QGradient *m_gradient;
+ friend class QFxGradientStop;
+};
+QML_DECLARE_TYPE(QFxGradient)
+
+class QFxRectPrivate;
+class Q_DECLARATIVE_EXPORT QFxRect : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor)
+ Q_PROPERTY(QFxGradient *gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(QFxPen * pen READ pen)
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius)
+public:
+ QFxRect(QFxItem *parent=0);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QColor tintColor() const;
+ void setTintColor(const QColor &);
+
+ QFxPen *pen();
+
+ QFxGradient *gradient() const;
+ void setGradient(QFxGradient *gradient);
+
+ qreal radius() const;
+ void setRadius(qreal radius);
+
+ virtual void dump(int depth);
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#endif
+
+#if defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+#endif
+
+private Q_SLOTS:
+ void doUpdate();
+
+private:
+ void generateRoundedRect();
+ void generateBorderedRect();
+#if defined(QFX_RENDER_QPAINTER)
+ void drawRect(QPainter &painter);
+#endif
+protected:
+ QFxRect(QFxRectPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxRect)
+ Q_DECLARE_PRIVATE(QFxRect)
+};
+QML_DECLARE_TYPE(QFxRect)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXRECT_H
diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h
new file mode 100644
index 0000000..8cafcbb
--- /dev/null
+++ b/src/declarative/fx/qfxrect_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXRECT_P_H
+#define QFXRECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxitem_p.h"
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFxGradient;
+
+class QFxRectPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxRect)
+
+public:
+ QFxRectPrivate()
+ : gradient(0), _pen(0), _radius(0)
+ {
+ }
+
+ ~QFxRectPrivate()
+ {
+ delete _pen;
+ }
+
+ void init()
+ {
+ }
+
+#if defined(QFX_RENDER_OPENGL)
+ GLTexture _rectTexture;
+#endif
+ QColor getColor();
+ QColor _color;
+ QFxGradient *gradient;
+ QColor _tintColor;
+ QFxPen *pen() {
+ if (!_pen) {
+ Q_Q(QFxRect);
+ _pen = new QFxPen;
+ QObject::connect(_pen, SIGNAL(updated()), q, SLOT(doUpdate()));
+ }
+ return _pen;
+ }
+ QFxPen *_pen;
+ qreal _radius;
+#if defined(QFX_RENDER_QPAINTER)
+ QPixmap _rectImage;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXRECT_P_H
diff --git a/src/declarative/fx/qfxreflectionfilter.cpp b/src/declarative/fx/qfxreflectionfilter.cpp
new file mode 100644
index 0000000..2e57aa7
--- /dev/null
+++ b/src/declarative/fx/qfxreflectionfilter.cpp
@@ -0,0 +1,352 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxreflectionfilter.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glbasicshaders.h>
+#include <gltexture.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+class QFxReflectionFilterPrivate
+{
+public:
+ QFxReflectionFilterPrivate()
+ : alpha(1), height(-1), offset(0), scale(1)
+ {
+ }
+ qreal alpha;
+ int height;
+ int offset;
+ qreal scale;
+};
+
+/*!
+ \qmlclass Reflection
+ \inherits Filter
+ \brief The Reflection filter reflects an item and its contents.
+
+ Here is an example of various Reflections applied to an image.
+
+ \qml
+HorizontalLayout {
+ Image {
+ source: "icon.png"
+ filter: Reflection { }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1; alpha: 0.5 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1; alpha: 0.5; height: 50 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1; alpha: 0.5; height: 50; scale: 0.5 }
+ }
+}
+ \endqml
+
+ \image reflection_example.png
+
+ Reflection is only supported when Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Reflection filter has no effect.
+*/
+
+/*!
+ \internal
+ \class QFxReflectionFilter
+ \ingroup group_effects
+ \brief The QFxReflectionFilter class allows you to add a reflection to an item.
+*/
+QFxReflectionFilter::QFxReflectionFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxReflectionFilterPrivate)
+{
+}
+
+QFxReflectionFilter::~QFxReflectionFilter()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \property QFxReflectionFilter::alpha
+ \brief the starting opacity of the reflection.
+
+ The starting opacity is the opacity closest to the item. The opacity will fade
+ from this value to zero over the height of the reflection.
+*/
+qreal QFxReflectionFilter::alpha() const
+{
+ return d->alpha;
+}
+
+void QFxReflectionFilter::setAlpha(qreal a)
+{
+ if (d->alpha == a) return;
+ d->alpha = a;
+ emit alphaChanged(a);
+ update();
+}
+
+/*!
+ \qmlproperty int Reflection::height
+
+ The height property controls how much of the item, in pixels, to reflect.
+ If it is set to the default value of -1, the whole item is reflected. If
+ it is set to 50, the bottom 50 pixels of the item are reflected. Data
+ binding could be used to reflect a percentage of the item.
+
+ \qml
+Image {
+ id: myImage
+ source: "album.png"
+ filter: Reflection {
+ height: myImage.height * 0.5
+ }
+}
+ \endqml
+ */
+/*!
+ \qmlproperty int Reflection::offset
+
+ The offset controls how far from the base of the item, in pixels, the
+ start of the reflection is placed. This can be used to create a nice
+ sliver of space between the item and its reflection or for more advanced
+ effects.
+
+ The default offset is 0 pixels.
+*/
+
+/*!
+ \qmlproperty real Reflection::alpha
+
+ The alpha value controls the starting opacity of the reflected item. If
+ set to the default value of 1, the reflected item starts completely opaque
+ and gradually fades to completely transparent. If set to less than one, the
+ reflection starts out partially transparent as though the item was sitting
+ on a visually less reflective surface.
+
+ Valid values are from 0 (which would be silly, but is allowed) to 1.
+*/
+/*!
+ \qmlproperty real Reflection::scale
+
+ When set to the default value of 1, the reflection is a 1:1 reflection of
+ the item. That is, each horizontal pixel in the item corresponds to one
+ horizontal pixel in the reflection.
+
+ When set a value other than 1, the reflection is scaled acordingly - less
+ than 1 scales it down and greater than 1 scales it up. The scale is applied
+ after the height parameter and does not effect the reflection offset.
+*/
+
+/*!
+ \property QFxReflectionFilter::height
+ \brief the height of the reflection, in pixels.
+*/
+int QFxReflectionFilter::height() const
+{
+ return d->height;
+}
+
+void QFxReflectionFilter::setHeight(int h)
+{
+ if (d->height == h) return;
+ d->height = h;
+ emit heightChanged(h);
+ update();
+}
+
+/*!
+ \property QFxReflectionFilter::offset
+ \brief the distance of the reflection from the item, in pixels.
+*/
+int QFxReflectionFilter::offset()
+{
+ return d->offset;
+}
+
+void QFxReflectionFilter::setOffset(int o)
+{
+ if (d->offset == o) return;
+ d->offset = o;
+ emit offsetChanged(o);
+ update();
+}
+
+/*!
+ \property QFxReflectionFilter::scale
+ \brief the scale of the reflection relative to the item.
+*/
+qreal QFxReflectionFilter::scale() const
+{
+ return d->scale;
+}
+
+void QFxReflectionFilter::setScale(qreal s)
+{
+ if (d->scale == s) return;
+ d->scale = s;
+ emit scaleChanged(s);
+ update();
+}
+
+static inline float min(float a, float b)
+{
+ return (a < b)?a:b;
+}
+
+void QFxReflectionFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+ if (r.isEmpty())
+ return;
+ float width = r.width();
+ float height = r.height();
+
+ float refHeight = height;
+ if (d->height > 0)
+ refHeight = min(height, d->height);
+
+ QSimpleCanvas::Matrix simpMat;
+ QSimpleCanvasItem *simpItem = 0;
+ if (isSimpleItem(&simpItem, &simpMat) &&
+ simpItem->glSimpleItemData(0, 0, 0, 0)) {
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+ GLTexture *texture = 0;
+
+ simpItem->glSimpleItemData(vertices, texVertices, &texture, 8);
+
+ GLfloat opacity[4];
+
+ float invRefHeight = 1. / refHeight;
+ for (int ii = 0; ii < 4; ++ii) {
+ float vertex = vertices[ii * 2 + 1];
+ float o = (1. - (height - vertex) * invRefHeight);
+ opacity[ii] = o * d->alpha * p.activeOpacity;
+ }
+
+ QSimpleCanvas::Matrix trans = p.activeTransform;
+ trans.rotate(180, 1, 0, 0);
+ trans.translate(0, -r.height() - d->offset);
+ if (d->scale != 1)
+ trans.scale(1, d->scale, 1);
+ trans.translate(0, -r.height());
+ trans *= simpMat;
+
+ glBindTexture(GL_TEXTURE_2D, texture->texture());
+
+ SingleTextureVertexOpacityShader *shader =
+ item->basicShaders()->singleTextureVertexOpacity();
+ shader->enable();
+ shader->setTransform(trans);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::TextureCoords, texVertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords, opacity, 1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::Vertices);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::TextureCoords);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords);
+
+ } else {
+ QGLFramebufferObject *fbo = renderToFBO();
+
+ float texWidth = width / float(fbo->width());
+ float texHeight = refHeight / float(fbo->height());
+
+ GLfloat invVertices[] = { width, height + d->scale * refHeight + d->offset,
+ 0, height + d->scale * refHeight + d->offset,
+ width, height + d->offset,
+ 0, height + d->offset };
+ GLfloat invTexVertices[] = { texWidth, texHeight,
+ 0, texHeight,
+ texWidth, 0,
+ 0, 0 };
+ GLfloat invOpacity[] = { 0, 0, d->alpha * p.activeOpacity, d->alpha * p.activeOpacity};
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+
+ SingleTextureVertexOpacityShader *shader =
+ item->basicShaders()->singleTextureVertexOpacity();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::Vertices, invVertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::TextureCoords, invTexVertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords, invOpacity, 1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::Vertices);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::TextureCoords);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords);
+
+ releaseFBO(fbo);
+ }
+
+ renderToScreen();
+
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QRectF QFxReflectionFilter::itemBoundingRect(const QRectF &r) const
+{
+ QRectF rv = r;
+ rv |= r.translated(0, r.height() + d->offset);
+ return rv;
+}
+
+QML_DEFINE_TYPE(QFxReflectionFilter,Reflection)
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxreflectionfilter.h b/src/declarative/fx/qfxreflectionfilter.h
new file mode 100644
index 0000000..6e56b5e
--- /dev/null
+++ b/src/declarative/fx/qfxreflectionfilter.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXREFLECTIONFILTER_H
+#define QFXREFLECTIONFILTER_H
+
+#include <QtDeclarative/qsimplecanvasfilter.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxReflectionFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxReflectionFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha NOTIFY alphaChanged)
+ Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
+ Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
+public:
+ QFxReflectionFilter(QObject *parent=0);
+ virtual ~QFxReflectionFilter();
+
+ qreal alpha() const;
+ void setAlpha(qreal);
+ int height() const;
+ void setHeight(int);
+ int offset();
+ void setOffset(int);
+ qreal scale() const;
+ void setScale(qreal);
+
+Q_SIGNALS:
+ void alphaChanged(qreal);
+ void heightChanged(int);
+ void offsetChanged(int);
+ void scaleChanged(qreal);
+
+protected:
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+ virtual QRectF itemBoundingRect(const QRectF &r) const;
+
+private:
+ Q_DISABLE_COPY(QFxReflectionFilter)
+ QFxReflectionFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxReflectionFilter)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXREFLECTIONFILTER_H
diff --git a/src/declarative/fx/qfxrepeater.cpp b/src/declarative/fx/qfxrepeater.cpp
new file mode 100644
index 0000000..0211ebb
--- /dev/null
+++ b/src/declarative/fx/qfxrepeater.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxrepeater.h"
+#include "qfxrepeater_p.h"
+#include "qmllistaccessor.h"
+#include <qlistmodelinterface.h>
+
+
+QT_BEGIN_NAMESPACE
+QFxRepeaterPrivate::QFxRepeaterPrivate()
+: component(0)
+{
+}
+
+QFxRepeaterPrivate::~QFxRepeaterPrivate()
+{
+}
+
+QFxItem *QFxRepeaterPrivate::addItem(QmlContext *ctxt, QFxItem *lastItem)
+{
+ Q_Q(QFxRepeater);
+ QObject *nobj = component->create(ctxt);
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (item) {
+ item->setParent(q->itemParent());
+ item->stackUnder(lastItem);
+ deletables << nobj;
+ } else {
+ delete nobj;
+ }
+
+ return item;
+}
+
+QML_DEFINE_TYPE(QFxRepeater,Repeater)
+
+/*!
+ \qmlclass Repeater
+ \inherits Item
+
+ \brief The Repeater item allows you to repeat a component based on a data source.
+
+ The Repeater item is used when you want to create a large number of
+ similar items. For each entry in the data source, an item is instantiated
+ in a context seeded with data from the data source. If the repeater will
+ be instantiating a large number of instances, it may be more efficient to
+ use one of Qt Declarative's \l {xmlViews}{view items}.
+
+ The data source may be either an object list, a string list or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component. The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes.
+
+ Items instantiated by the Repeater are inserted, in order, as
+ children of the Repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This is to allow
+ you to use a Repeater inside a layout. The following QML example shows how
+ the instantiated items would visually appear stacked between the red and
+ blue rectangles.
+
+ \snippet doc/src/snippets/declarative/repeater.qml 0
+
+ \image repeater.png
+
+ The repeater instance continues to own all items it instantiates, even
+ if they are otherwise manipulated. It is illegal to manually remove an item
+ created by the Repeater.
+ */
+
+/*!
+ \internal
+ \class QFxRepeater
+ \ingroup group_utility
+ \qmlclass Repeater
+
+ \brief The QFxRepeater class allows you to repeat a component based on a
+ data source.
+
+ The QFxRepeater class is used when you want to create a large number of
+ similar items. For each entry in the data source, an item is instantiated
+ in a context seeded with data from the data source.
+
+ The data source may be either an object list, a string list or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component. The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes.
+
+ As a special case the data source can also be merely a number. In this case it will
+ create that many instances of the component. They will also be assigned an index
+ based on the order they are created.
+
+ Items instantiated by the QFxRepeater class are inserted, in order, as
+ children of the repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This is to allow
+ you to use a repeater inside a layout. The following QML example shows how
+ the instantiated items would visually appear stacked between the red and
+ blue rectangles.
+
+ \snippet doc/src/snippets/declarative/repeater.qml 0
+
+ The QFxRepeater instance continues to own all items it instantiates, even
+ if they are otherwise manipulated. It is illegal to manually delete an item
+ created by the repeater. On destruction, the repeater will clean up any
+ items it has instantiated.
+
+
+ XXX Repeater is very conservative in how it instatiates/deletes items. Also
+ new model entries will not be created and old ones will not be removed.
+ */
+
+/*!
+ Create a new QFxRepeater instance.
+ */
+QFxRepeater::QFxRepeater(QFxItem *parent)
+ : QFxItem(*(new QFxRepeaterPrivate), parent)
+{
+}
+
+/*!
+ \internal
+ */
+QFxRepeater::QFxRepeater(QFxRepeaterPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+}
+
+/*!
+ Destroy the repeater instance. All items it instantiated are also
+ destroyed.
+ */
+QFxRepeater::~QFxRepeater()
+{
+}
+
+/*!
+ \qmlproperty any Repeater::dataSource
+
+ The Repeater's data source.
+
+ The data source may be either an object list, a string list or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component. The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes.
+
+ As a special case the data source can also be merely a number. In this case it will
+ create that many instances of the component. They will also be assigned an index
+ based on the order they are created.
+*/
+
+/*!
+ \property QFxRepeater::dataSource
+ \brief The source of data for the repeater.
+ */
+QVariant QFxRepeater::dataSource() const
+{
+ return QVariant();
+}
+
+void QFxRepeater::setDataSource(const QVariant &v)
+{
+ Q_D(QFxRepeater);
+ d->dataSource = v;
+ regenerate();
+}
+
+/*!
+ \qmlproperty Component Repeater::component
+ \default
+
+ The component to repeat.
+ */
+/*!
+ \property QFxRepeater::component
+ \brief The component to repeat.
+ */
+QmlComponent *QFxRepeater::component() const
+{
+ Q_D(const QFxRepeater);
+ return d->component;
+}
+
+void QFxRepeater::setComponent(QmlComponent *_c)
+{
+ Q_D(QFxRepeater);
+ d->component = _c;
+ regenerate();
+}
+
+/*!
+ \internal
+ */
+void QFxRepeater::componentComplete()
+{
+ QFxItem::componentComplete();
+ regenerate();
+}
+
+/*!
+ \internal
+ */
+void QFxRepeater::parentChanged(QSimpleCanvasItem *o, QSimpleCanvasItem *n)
+{
+ QFxItem::parentChanged(o, n);
+ regenerate();
+}
+
+/*!
+ \internal
+ */
+void QFxRepeater::regenerate()
+{
+ Q_D(QFxRepeater);
+
+ qDeleteAll(d->deletables);
+ d->deletables.clear();
+ if (!d->component || !itemParent() || !isComponentComplete())
+ return;
+
+ QFxItem *lastItem = this;
+
+ if (d->dataSource.type() == QVariant::StringList) {
+ QStringList sl = qvariant_cast<QStringList>(d->dataSource);
+
+ for (int ii = 0; ii < sl.size(); ++ii) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+ ctxt->setContextProperty(QLatin1String("modelData"), sl.at(ii));
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ } else if (QmlMetaType::isList(d->dataSource)) {
+ int cnt = QmlMetaType::listCount(d->dataSource);
+ if (cnt <= 0)
+ return;
+
+ for (int ii = 0; ii < cnt; ++ii) {
+ QVariant v = QmlMetaType::listAt(d->dataSource, ii);
+ QObject *o = QmlMetaType::toQObject(v);
+
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+ ctxt->setContextProperty(QLatin1String("modelData"), o);
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ } else if (QListModelInterface *model = qobject_cast<QListModelInterface*>(d->dataSource.value<QObject*>())) {
+ int cnt = model->count();
+ if (cnt <= 0)
+ return;
+
+ for (int ii = 0; ii < cnt; ++ii) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+
+ QList<int> roles = model->roles();
+ QHash<int,QVariant> data = model->data(ii,roles);
+ for (int j = 0; j < roles.size(); ++j) {
+ ctxt->setContextProperty(model->toString(roles.at(j)), data.value(roles.at(j)));
+ }
+
+ //for compatability with other lists, assign data if there is only a single role
+ if (roles.size() == 1)
+ ctxt->setContextProperty(QLatin1String("modelData"), data.value(roles.at(0)));
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ } else if (QObject *object = d->dataSource.value<QObject*>()) {
+ // A single object (i.e. list of size 1).
+ // Properties are the roles (excluding objectName).
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), QVariant(0));
+ for (int ii = 1; ii < object->metaObject()->propertyCount(); ++ii) {
+ const QMetaProperty &prop = object->metaObject()->property(ii);
+ ctxt->setContextProperty(QLatin1String(prop.name()), prop.read(object));
+ }
+
+ //for compatability with other lists, assign data if there is only a single role (excluding objectName)
+ if (object->metaObject()->propertyCount() == 2) {
+ const QMetaProperty &prop = object->metaObject()->property(1);
+ ctxt->setContextProperty(QLatin1String("modelData"), prop.read(object));
+ }
+
+ d->addItem(ctxt, lastItem);
+
+ } else if (d->dataSource.canConvert(QVariant::Int)){
+
+ int count = qvariant_cast<int>(d->dataSource);
+
+ for (int ii = 0; ii < count; ++ii) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxrepeater.h b/src/declarative/fx/qfxrepeater.h
new file mode 100644
index 0000000..c1b194a
--- /dev/null
+++ b/src/declarative/fx/qfxrepeater.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXREPEATER_H
+#define QFXREPEATER_H
+
+#include <QtDeclarative/qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxRepeaterPrivate;
+class Q_DECLARATIVE_EXPORT QFxRepeater : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant dataSource READ dataSource WRITE setDataSource)
+ Q_PROPERTY(QmlComponent *component READ component WRITE setComponent)
+ Q_CLASSINFO("DefaultProperty", "component")
+public:
+ QFxRepeater(QFxItem *parent=0);
+ virtual ~QFxRepeater();
+
+ QVariant dataSource() const;
+ void setDataSource(const QVariant &);
+
+ QmlComponent *component() const;
+ void setComponent(QmlComponent *);
+
+private:
+ void regenerate();
+
+protected:
+ virtual void componentComplete();
+ virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *);
+ QFxRepeater(QFxRepeaterPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxRepeater)
+ Q_DECLARE_PRIVATE(QFxRepeater)
+};
+QML_DECLARE_TYPE(QFxRepeater)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // _QFXREPEATER_H_
diff --git a/src/declarative/fx/qfxrepeater_p.h b/src/declarative/fx/qfxrepeater_p.h
new file mode 100644
index 0000000..ba69658
--- /dev/null
+++ b/src/declarative/fx/qfxrepeater_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXREPEATER_P_H
+#define QFXREPEATER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxitem_p.h"
+#include "qfxrepeater.h"
+#include <QPointer>
+
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QFxRepeaterPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxRepeater)
+
+public:
+ QFxRepeaterPrivate();
+ ~QFxRepeaterPrivate();
+
+ QFxItem *addItem(QmlContext *ctxt, QFxItem *lastItem);
+
+ QVariant dataSource;
+ QmlComponent *component;
+
+ QList<QPointer<QObject> > deletables;
+};
+
+QT_END_NAMESPACE
+#endif // QFXREPEATER_P_H
diff --git a/src/declarative/fx/qfxscalegrid.cpp b/src/declarative/fx/qfxscalegrid.cpp
new file mode 100644
index 0000000..abe8e0d
--- /dev/null
+++ b/src/declarative/fx/qfxscalegrid.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QBuffer>
+#include <qml.h>
+#include "qfxscalegrid.h"
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \internal
+ \class QFxScaleGrid
+ \brief The QFxScaleGrid class allows you to specify a 3x3 grid to use in scaling an image.
+
+ A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below:
+ \image scalegrid.png
+
+ When the image is scaled:
+ \list
+ \i the corners (sections 1, 3, 7, and 9) are not scaled at all
+ \i the middle (section 5) is scaled both horizontally and vertically
+ \i sections 2 and 8 are scaled horizontally
+ \i sections 4 and 6 are scaled vertically
+ \endlist
+
+ A common way of specifying a scale grid is to create an sci file. An sci file uses a simple
+ text-based format that specifies each grid line, as well as the associated image file. An example of an sci file's contents:
+ \code
+ gridLeft: 10
+ gridTop: 10
+ gridBottom: 10
+ gridRight: 10
+ imageFile: picture.png
+ \endcode
+*/
+QML_DEFINE_NOCREATE_TYPE(QFxScaleGrid)
+
+QFxScaleGrid::QFxScaleGrid() : QObject(), _left(0), _top(0), _right(0), _bottom(0)
+{
+}
+
+QFxScaleGrid::~QFxScaleGrid()
+{
+}
+
+bool QFxScaleGrid::isNull() const
+{
+ return !_left && !_top && !_right && !_bottom;
+}
+
+/*!
+ \property QFxScaleGrid::left
+ \brief the position of the left grid line as an offset from the left side of the image.
+*/
+void QFxScaleGrid::setLeft(int pos)
+{
+ _left = pos;
+}
+
+/*!
+ \property QFxScaleGrid::top
+ \brief the position of the top grid line as an offset from the top of the image.
+*/
+void QFxScaleGrid::setTop(int pos)
+{
+ _top = pos;
+}
+
+/*!
+ \property QFxScaleGrid::right
+ \brief the position of the right grid line as an offset from the right side of the image.
+*/
+void QFxScaleGrid::setRight(int pos)
+{
+ _right = pos;
+}
+
+/*!
+ \property QFxScaleGrid::bottom
+ \brief the position of the bottom grid line as an offset from the bottom of the image.
+*/
+void QFxScaleGrid::setBottom(int pos)
+{
+ _bottom = pos;
+}
+
+QFxGridScaledImage::QFxGridScaledImage()
+: _l(-1), _r(-1), _t(-1), _b(-1)
+{
+}
+
+QFxGridScaledImage::QFxGridScaledImage(const QFxGridScaledImage &o)
+: _l(o._l), _r(o._r), _t(o._t), _b(o._b), _pix(o._pix)
+{
+}
+
+QFxGridScaledImage &QFxGridScaledImage::operator=(const QFxGridScaledImage &o)
+{
+ _l = o._l;
+ _r = o._r;
+ _t = o._t;
+ _b = o._b;
+ _pix = o._pix;
+ return *this;
+}
+
+QFxGridScaledImage::QFxGridScaledImage(QIODevice *data)
+: _l(-1), _r(-1), _t(-1), _b(-1)
+{
+ int l = -1;
+ int r = -1;
+ int t = -1;
+ int b = -1;
+ QString imgFile;
+
+ while(!data->atEnd()) {
+ QString line = QString::fromUtf8(data->readLine().trimmed());
+ if (line.isEmpty() || line.startsWith(QLatin1String("#")))
+ continue;
+
+ QStringList list = line.split(QLatin1Char(':'));
+ if (list.count() != 2)
+ return;
+
+ list[0] = list[0].trimmed();
+ list[1] = list[1].trimmed();
+
+ if (list[0] == QLatin1String("gridLeft"))
+ l = list[1].toInt();
+ else if (list[0] == QLatin1String("gridRight"))
+ r = list[1].toInt();
+ else if (list[0] == QLatin1String("gridTop"))
+ t = list[1].toInt();
+ else if (list[0] == QLatin1String("gridBottom"))
+ b = list[1].toInt();
+ else if (list[0] == QLatin1String("imageFile"))
+ imgFile = list[1];
+ }
+
+ if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty())
+ return;
+
+ _l = l; _r = r; _t = t; _b = b;
+
+ _pix = imgFile;
+}
+
+bool QFxGridScaledImage::isValid() const
+{
+ return _l >= 0;
+}
+
+int QFxGridScaledImage::gridLeft() const
+{
+ return _l;
+}
+
+int QFxGridScaledImage::gridRight() const
+{
+ return _r;
+}
+
+int QFxGridScaledImage::gridTop() const
+{
+ return _t;
+}
+
+int QFxGridScaledImage::gridBottom() const
+{
+ return _b;
+}
+
+QString QFxGridScaledImage::pixmapUrl() const
+{
+ return _pix;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxscalegrid.h b/src/declarative/fx/qfxscalegrid.h
new file mode 100644
index 0000000..c59cb32
--- /dev/null
+++ b/src/declarative/fx/qfxscalegrid.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXSCALEGRID_H
+#define QFXSCALEGRID_H
+
+#include <QtCore/QString>
+#include <QtCore/QObject>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qsimplecanvas.h>
+#include <QtDeclarative/qfxpixmap.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxScaleGrid : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int left READ left WRITE setLeft)
+ Q_PROPERTY(int top READ top WRITE setTop)
+ Q_PROPERTY(int right READ right WRITE setRight)
+ Q_PROPERTY(int bottom READ bottom WRITE setBottom)
+public:
+ QFxScaleGrid();
+ ~QFxScaleGrid();
+
+ bool isNull() const;
+
+ int left() const { return _left; }
+ void setLeft(int);
+
+ int top() const { return _top; }
+ void setTop(int);
+
+ int right() const { return _right; }
+ void setRight(int);
+
+ int bottom() const { return _bottom; }
+ void setBottom(int);
+
+private:
+ int _left;
+ int _top;
+ int _right;
+ int _bottom;
+};
+
+class Q_DECLARATIVE_EXPORT QFxGridScaledImage
+{
+public:
+ QFxGridScaledImage();
+ QFxGridScaledImage(const QFxGridScaledImage &);
+ QFxGridScaledImage(QIODevice*);
+ QFxGridScaledImage &operator=(const QFxGridScaledImage &);
+ bool isValid() const;
+ int gridLeft() const;
+ int gridRight() const;
+ int gridTop() const;
+ int gridBottom() const;
+
+ QString pixmapUrl() const;
+
+private:
+ int _l;
+ int _r;
+ int _t;
+ int _b;
+ QString _pix;
+};
+QML_DECLARE_TYPE(QFxScaleGrid)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXSCALEGRID_H
diff --git a/src/declarative/fx/qfxshadowfilter.cpp b/src/declarative/fx/qfxshadowfilter.cpp
new file mode 100644
index 0000000..10c332c
--- /dev/null
+++ b/src/declarative/fx/qfxshadowfilter.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxshadowfilter.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glbasicshaders.h>
+#endif
+
+class QFxShadowFilterPrivate
+
+QT_BEGIN_NAMESPACE
+{
+public:
+ QFxShadowFilterPrivate()
+ : x(0), y(0)
+ {
+ }
+
+ int x;
+ int y;
+};
+
+/*!
+ \qmlclass Shadow
+ \brief The Shadow filter casts a drop shadow.
+ \inherits Filter
+
+ Shadows work on all visual elements - including transparent and masked
+ images.
+
+ \table
+ \row
+ \o \image shadow_example.png
+ \o
+ \qml
+Rect {
+ radius: 5
+ color: "lightsteelblue"
+ width: 100
+ height: 100
+ filter: Shadow {
+ yOffset: 8
+ xOffset: 8
+ }
+}
+
+Image {
+ source: "pics/qtlogo.png"
+ filter: Shadow {
+ yOffset: 8
+ xOffset: 8
+ }
+}
+ \endqml
+ \endtable
+
+ Shadows are only supported when Qt Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Shadow filter has no effect.
+*/
+
+/*!
+ \internal
+ \class QFxShadowFilter
+ \ingroup group_effects
+ \brief The QFxShadowFilter class allows you to add a shadow to an item.
+*/
+
+QFxShadowFilter::QFxShadowFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxShadowFilterPrivate)
+{
+}
+
+QFxShadowFilter::~QFxShadowFilter()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \qmlproperty int Shadow::xOffset
+ \qmlproperty int Shadow::yOffset
+
+ Specify the x and y offset of the shadow relative to the item.
+*/
+
+int QFxShadowFilter::xOffset() const
+{
+ return d->x;
+}
+
+/*!
+ \property QFxShadowFilter::xOffset
+ \brief the x offset of the shadow relative to the item.
+*/
+void QFxShadowFilter::setXOffset(int offset)
+{
+ if (d->x == offset) return;
+ d->x = offset;
+ emit offsetChanged(d->x, d->y);
+}
+
+/*!
+ \property QFxShadowFilter::yOffset
+ \brief the y offset of the shadow relative to the item.
+*/
+int QFxShadowFilter::yOffset() const
+{
+ return d->y;
+}
+
+void QFxShadowFilter::setYOffset(int offset)
+{
+ if (d->y == offset) return;
+ d->y = offset;
+ emit offsetChanged(d->x, d->y);
+}
+
+QRectF QFxShadowFilter::itemBoundingRect(const QRectF &r) const
+{
+ QRectF rv = r;
+ rv |= r.translated(xOffset(), yOffset());
+ return rv;
+}
+
+void QFxShadowFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+
+ QGLFramebufferObject *fbo = renderToFBO();
+
+ float width = r.width();
+ float height = r.height();
+
+ float texWidth = width / float(fbo->width());
+ float texHeight = height / float(fbo->height());
+
+ GLfloat vertices[] = { d->x, height + d->y,
+ width + d->x, height + d->y,
+ d->x, d->y,
+ d->x + width, d->y };
+ GLfloat texVertices[] = { 0, 0,
+ texWidth, 0,
+ 0, texHeight,
+ texWidth, texHeight };
+
+ SingleTextureShadowShader *shader = item->basicShaders()->singleTextureShadow();
+ shader->enable();
+ shader->setOpacity(0.8 * p.activeOpacity);
+ shader->setTransform(p.activeTransform);
+
+ shader->setAttributeArray(SingleTextureShadowShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShadowShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShadowShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShadowShader::TextureCoords);
+
+ releaseFBO(fbo);
+
+ renderToScreen();
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QML_DEFINE_TYPE(QFxShadowFilter,Shadow)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxshadowfilter.h b/src/declarative/fx/qfxshadowfilter.h
new file mode 100644
index 0000000..67d165a
--- /dev/null
+++ b/src/declarative/fx/qfxshadowfilter.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXSHADOWFILTER_H
+#define QFXSHADOWFILTER_H
+
+#include <QtDeclarative/qsimplecanvasfilter.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxShadowFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxShadowFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+ Q_PROPERTY(int xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged)
+ Q_PROPERTY(int yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged)
+public:
+ QFxShadowFilter(QObject *parent=0);
+ virtual ~QFxShadowFilter();
+
+ int xOffset() const;
+ void setXOffset(int offset);
+
+ int yOffset() const;
+ void setYOffset(int offset);
+
+Q_SIGNALS:
+ void offsetChanged(int, int);
+
+protected:
+ virtual QRectF itemBoundingRect(const QRectF &) const;
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+
+private:
+ QFxShadowFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxShadowFilter)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // _QFXSHADOWFILTER_H_
diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp
new file mode 100644
index 0000000..702ec81
--- /dev/null
+++ b/src/declarative/fx/qfxtext.cpp
@@ -0,0 +1,950 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxtext.h"
+#include "qfxtext_p.h"
+
+#include <private/qtextcontrol_p.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+#endif
+
+#include <qfxperf.h>
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QGraphicsSceneMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxText,Text)
+
+/*!
+ \qmlclass Text QFxText
+ \brief The Text item allows you to add formatted text to a scene.
+ \inherits Item
+
+ It can display both plain and rich text. For example:
+
+ \qml
+ Text { text: "Hello World!"; font.family: "Helvetica"; font.size: 24; color: "red" }
+ Text { text: "<b>Hello</b> <i>World!</i>" }
+ \endqml
+
+ \image declarative-text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \c wrap is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \c elide property can alternatively be used to fit a single line of
+ plain text to a set width.
+
+ Text provides read-only text. For editable text, see \l TextEdit.
+*/
+
+/*!
+ \internal
+ \class QFxText
+ \qmlclass Text
+ \ingroup group_coreitems
+
+ \brief The QFxText class provides a formatted text item that you can add to a QFxView.
+
+ Text was designed for read-only text; it does not allow for any text editing.
+ It can display both plain and rich text. For example:
+
+ \qml
+ Text { text: "Hello World!"; font.family: "Helvetica"; font.size: 24; color: "red" }
+ Text { text: "<b>Hello</b> <i>World!</i>" }
+ \endqml
+
+ \image text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \c wrap is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \c elide property can alternatively be used to fit a line of plain text to a set width.
+
+ A QFxText object can be instantiated in Qml using the tag \c Text.
+*/
+QFxText::QFxText(QFxItem *parent)
+ : QFxItem(*(new QFxTextPrivate), parent)
+{
+ Q_D(QFxText);
+ d->init();
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setOptions(SimpleItem | HasContents | QFxText::MouseEvents);
+}
+
+QFxText::QFxText(QFxTextPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxText);
+ d->init();
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setOptions(SimpleItem | HasContents | QFxText::MouseEvents);
+}
+
+QFxText::~QFxText()
+{
+}
+
+/*!
+ \qmlproperty string Text::font.family
+ \qmlproperty bool Text::font.bold
+ \qmlproperty bool Text::font.italic
+ \qmlproperty real Text::font.size
+
+ Set the Text's font attributes.
+
+ \note \c font.size sets the font's point size (not pixel size).
+*/
+
+/*!
+ \property QFxText::font
+ \brief the font used to display the text.
+*/
+
+QmlFont *QFxText::font()
+{
+ Q_D(QFxText);
+ return d->font();
+}
+
+void QFxText::setText(const QString &n)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::QFxText_setText> st;
+#endif
+ Q_D(QFxText);
+ if (d->text == n)
+ return;
+
+ d->richText = Qt::mightBeRichText(n); // ### what's the cost?
+ if (d->richText) {
+ if (!d->doc)
+ {
+ d->control = new QTextControl(this);
+ d->control->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ d->doc = d->control->document();
+ d->doc->setDocumentMargin(0);
+ }
+ d->doc->setHtml(n);
+ }
+
+ d->text = n;
+ d->imgDirty = true;
+ d->updateSize();
+ emit textChanged(d->text);
+ update();
+}
+
+/*!
+ \qmlproperty string Text::text
+ \default
+
+ The text to display. Text supports both plain and rich text strings.
+
+ The item will try to automatically determine whether the text should
+ be treated as rich text. This determination is made using Qt::mightBeRichText().
+*/
+QString QFxText::text() const
+{
+ Q_D(const QFxText);
+ return d->text;
+}
+
+void QFxText::setColor(const QColor &color)
+{
+ Q_D(QFxText);
+ if (d->color == color)
+ return;
+
+ d->imgDirty = true;
+ d->color = color;
+ update();
+}
+
+/*!
+ \qmlproperty color Text::color
+
+ The text color.
+
+ \qml
+ //green text using hexadecimal notation
+ Text { color: "#00FF00"; ... }
+
+ //steelblue text using SVG color name
+ Text { color: "steelblue"; ... }
+ \endqml
+*/
+
+QColor QFxText::color() const
+{
+ Q_D(const QFxText);
+ return d->color;
+}
+
+/*!
+ \qmlproperty enumeration Text::style
+
+ Set an additional text style.
+
+ Supported text styles are \c Normal, \c Outline, \c Raised and \c Sunken.
+
+ \qml
+ HorizontalLayout {
+ Text { font.size: 24; text: "Normal" }
+ Text { font.size: 24; text: "Raised"; style: "Raised"; styleColor: "#AAAAAA" }
+ Text { font.size: 24; text: "Outline"; style: "Outline"; styleColor: "red" }
+ Text { font.size: 24; text: "Sunken"; style: "Sunken"; styleColor: "#AAAAAA" }
+ }
+ \endqml
+
+ \image declarative-textstyle.png
+*/
+
+/*!
+ \property QFxText::style
+ \brief an additional style of the text to display.
+
+ By default, the text style is Normal.
+
+ \note This property is used to support text styles not natively
+ handled by QFont or QPainter::drawText().
+*/
+QFxText::TextStyle QFxText::style() const
+{
+ Q_D(const QFxText);
+ return d->style;
+}
+
+void QFxText::setStyle(QFxText::TextStyle style)
+{
+ Q_D(QFxText);
+ if (d->style == style)
+ return;
+
+ d->imgDirty = true;
+ d->style = style;
+ update();
+}
+
+void QFxText::setStyleColor(const QColor &color)
+{
+ Q_D(QFxText);
+ if (d->styleColor == color)
+ return;
+
+ d->imgDirty = true;
+ d->styleColor = color;
+ update();
+}
+
+/*!
+ \qmlproperty color Text::styleColor
+
+ Defines the secondary color used by text styles.
+
+ \c styleColor is used as the outline color for outlined text, and as the
+ shadow color for raised or sunken text. If no style has been set, it is not
+ used at all.
+ */
+QColor QFxText::styleColor() const
+{
+ Q_D(const QFxText);
+ return d->styleColor;
+}
+
+/*!
+ \qmlproperty enumeration Text::hAlign
+ \qmlproperty enumeration Text::vAlign
+
+ Sets the horizontal and vertical alignment of the text within the Text items
+ width and height. By default, the text is top-left aligned.
+
+ The valid values for \c hAlign are \c AlignLeft, \c AlignRight and
+ \c AlignHCenter. The valid values for \c vAlign are \c AlignTop, \c AlignBottom
+ and \c AlignVCenter.
+*/
+
+/*!
+ \property QFxText::hAlign
+ \brief the horizontal alignment of the text.
+
+ Valid values are \c AlignLeft, \c AlignRight, and \c AlignHCenter. The default value is \c AlignLeft.
+*/
+QFxText::HAlignment QFxText::hAlign() const
+{
+ Q_D(const QFxText);
+ return d->hAlign;
+}
+
+void QFxText::setHAlign(HAlignment align)
+{
+ Q_D(QFxText);
+ d->hAlign = align;
+}
+
+/*!
+ \property QFxText::vAlign
+ \brief the vertical alignment of the text.
+
+ Valid values are \c AlignTop, \c AlignBottom, and \c AlignVCenter. The default value is \c AlignTop.
+*/
+QFxText::VAlignment QFxText::vAlign() const
+{
+ Q_D(const QFxText);
+ return d->vAlign;
+}
+
+void QFxText::setVAlign(VAlignment align)
+{
+ Q_D(QFxText);
+ d->vAlign = align;
+}
+
+/*!
+ \qmlproperty bool Text::wrap
+
+ Set this property to wrap the text to the Text item's width. The text will only
+ wrap if an explicit width has been set.
+
+ Wrapping is done on word boundaries (i.e. it is a "word-wrap"). If the text cannot be
+ word-wrapped to the specified width it will be partially drawn outside of the item's bounds.
+ If this is undesirable then enable clipping on the item (Item::clip).
+
+ Wrapping is off by default.
+*/
+//### Future may provide choice of wrap modes, such as QTextOption::WrapAtWordBoundaryOrAnywhere
+bool QFxText::wrap() const
+{
+ Q_D(const QFxText);
+ return d->wrap;
+}
+
+void QFxText::setWrap(bool w)
+{
+ Q_D(QFxText);
+ if (w == d->wrap)
+ return;
+
+ d->wrap = w;
+
+ d->imgDirty = true;
+ d->updateSize();
+}
+
+/*!
+ \qmlproperty Qt::TextElideMode Text::elide
+
+ Set this property to elide parts of the text fit to the Text item's width.
+ The text will only elide if an explicit width has been set.
+
+ This property cannot be used with wrap enabled or with rich text.
+
+ Eliding can be ElideNone, ElideLeft, ElideMiddle, or ElideRight.
+
+ ElideNone is the default.
+*/
+Qt::TextElideMode QFxText::elideMode() const
+{
+ Q_D(const QFxText);
+ return d->elideMode;
+}
+
+void QFxText::setElideMode(Qt::TextElideMode mode)
+{
+ Q_D(QFxText);
+ if (mode == d->elideMode)
+ return;
+
+ d->elideMode = mode;
+
+ d->imgDirty = true;
+ d->updateSize();
+}
+
+
+QString QFxText::activeLink() const
+{
+ Q_D(const QFxText);
+ return d->activeLink;
+}
+
+void QFxText::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QFxText);
+ if (newGeometry.width() != oldGeometry.width()) {
+ if (d->wrap || d->elideMode != Qt::ElideNone) {
+ d->imgDirty = true;
+ d->updateSize();
+ }
+ }
+ QFxItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+
+void QFxText::fontChanged()
+{
+ Q_D(QFxText);
+ d->imgDirty = true;
+ d->updateSize();
+ emit update();
+}
+
+void QFxTextPrivate::updateSize()
+{
+ Q_Q(QFxText);
+ if (q->isComponentComplete()) {
+ if (text.isEmpty()) {
+ return;
+ }
+ QFont f; if (_font) f = _font->font();
+ QFontMetrics fm(f);
+ int dy = q->height();
+
+ QString tmp;
+ QSize size(0, 0);
+
+ //setup instance of QTextLayout for all cases other than richtext
+ if (!richText)
+ {
+ tmp = text;
+ tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ singleline = !tmp.contains(QChar::LineSeparator);
+ if (singleline && elideMode != Qt::ElideNone && q->widthValid())
+ tmp = fm.elidedText(tmp,elideMode,q->width()); // XXX still worth layout...?
+ layout.clearLayout();
+ layout.setFont(f);
+ layout.setText(tmp);
+ size = setupTextLayout(&layout);
+ cachedLayoutSize = size;
+ }
+ if (richText) {
+ singleline = false; // richtext can't elide or be optimized for single-line case
+ doc->setDefaultFont(f);
+ QTextOption option((Qt::Alignment)int(hAlign | vAlign));
+ if (wrap)
+ option.setWrapMode(QTextOption::WordWrap);
+ else
+ option.setWrapMode(QTextOption::NoWrap);
+ doc->setDefaultTextOption(option);
+ if (wrap && !q->heightValid() && q->widthValid())
+ doc->setTextWidth(q->width());
+ else
+ doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
+ dy -= (int)doc->size().height();
+ } else {
+ dy -= size.height();
+ }
+ int yoff = 0;
+
+ if (q->heightValid()) {
+ if (vAlign == QFxText::AlignBottom)
+ yoff = dy;
+ else if (vAlign == QFxText::AlignVCenter)
+ yoff = dy/2;
+ }
+ q->setBaselineOffset(fm.ascent() + yoff);
+
+ if (!q->widthValid()) {
+ int newWidth = (richText ? (int)doc->idealWidth() : size.width());
+ q->setImplicitWidth(newWidth);
+ }
+ if (!q->heightValid()) {
+ if (richText) {
+ q->setImplicitHeight((int)doc->size().height());
+ } else {
+ q->setImplicitHeight(size.height());
+ }
+ }
+ } else {
+ dirty = true;
+ }
+}
+
+// ### text layout handling should be profiled and optimized as needed
+// what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
+
+void QFxText::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << propertyInfo();
+ QFxItem::dump(depth);
+}
+
+QString QFxText::propertyInfo() const
+{
+ Q_D(const QFxText);
+ return QChar(QLatin1Char('\"')) + d->text + QChar(QLatin1Char('\"'));
+}
+
+void QFxTextPrivate::drawOutline()
+{
+ QPixmap img = QPixmap(imgCache.size());
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ QPoint pos(imgCache.rect().topLeft());
+ pos += QPoint(-1, 0);
+ ppm.drawPixmap(pos, imgStyleCache);
+ pos += QPoint(2, 0);
+ ppm.drawPixmap(pos, imgStyleCache);
+ pos += QPoint(-1, -1);
+ ppm.drawPixmap(pos, imgStyleCache);
+ pos += QPoint(0, 2);
+ ppm.drawPixmap(pos, imgStyleCache);
+
+ pos += QPoint(0, -1);
+ ppm.drawPixmap(pos, imgCache);
+ ppm.end();
+
+ imgCache = img;
+}
+
+void QFxTextPrivate::drawOutline(int yOffset)
+{
+ QPixmap img = QPixmap(imgCache.size());
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ QPoint pos(imgCache.rect().topLeft());
+ pos += QPoint(0, yOffset);
+ ppm.drawPixmap(pos, imgStyleCache);
+
+ pos += QPoint(0, -yOffset);
+ ppm.drawPixmap(pos, imgCache);
+ ppm.end();
+
+ imgCache = img;
+}
+
+QSize QFxTextPrivate::setupTextLayout(QTextLayout *layout)
+{
+ Q_Q(QFxText);
+ layout->setCacheEnabled(true);
+
+ QFont f; if (_font) f = _font->font();
+ QFontMetrics fm = QFontMetrics(f);
+
+ int height = 0;
+ qreal widthUsed = 0;
+ qreal lineWidth = 0;
+
+ //set manual width
+ if ((wrap || elideMode != Qt::ElideNone) && q->widthValid())
+ lineWidth = q->width();
+
+ layout->beginLayout();
+
+ while (1) {
+ QTextLine line = layout->createLine();
+ if (!line.isValid())
+ break;
+
+ if ((wrap || elideMode != Qt::ElideNone) && q->widthValid())
+ line.setLineWidth(lineWidth);
+ }
+ layout->endLayout();
+
+ for (int i = 0; i < layout->lineCount(); ++i) {
+ QTextLine line = layout->lineAt(i);
+ widthUsed = qMax(widthUsed, line.naturalTextWidth());
+ line.setPosition(QPointF(0, height));
+ height += int(line.height());
+ }
+ return QSize((int)widthUsed, height);
+}
+
+QPixmap QFxTextPrivate::wrappedTextImage(bool drawStyle)
+{
+ //do layout
+ QFont f; if (_font) f = _font->font();
+ QSize size = cachedLayoutSize;
+
+ int x = 0;
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ if (hAlign == QFxText::AlignLeft) {
+ x = 0;
+ } else if (hAlign == QFxText::AlignRight) {
+ x = size.width() - (int)line.naturalTextWidth();
+ } else if (hAlign == QFxText::AlignHCenter) {
+ x = (size.width() - (int)line.naturalTextWidth()) / 2;
+ }
+ line.setPosition(QPoint(x, (int)line.y()));
+ }
+
+ //paint text
+ QPixmap img(size);
+ img.fill(Qt::transparent);
+ QPainter p(&img);
+ if (drawStyle) {
+ p.setPen(styleColor);
+ }
+ else
+ p.setPen(color);
+ p.setFont(f);
+ layout.draw(&p, QPointF(0, 0));
+ return img;
+}
+
+QPixmap QFxTextPrivate::richTextImage(bool drawStyle)
+{
+ QSize size = doc->size().toSize();
+
+ //paint text
+ QPixmap img(size);
+ img.fill(Qt::transparent);
+ QPainter p(&img);
+
+ if (drawStyle) {
+ QPalette pal = control->palette();
+ pal.setColor(QPalette::Text, styleColor);
+ control->setPalette(pal);
+ QTextOption colorOption;
+ colorOption.setFlags(QTextOption::SuppressColors);
+ doc->setDefaultTextOption(colorOption);
+ } else {
+ QPalette pal = control->palette();
+ pal.setColor(QPalette::Text, color);
+ control->setPalette(pal);
+ }
+ control->drawContents(&p, QRectF(QPointF(0, 0), QSizeF(size)));
+ if (drawStyle)
+ doc->setDefaultTextOption(QTextOption());
+ return img;
+}
+
+void QFxTextPrivate::checkImgCache()
+{
+ if (!imgDirty)
+ return;
+
+ bool empty = text.isEmpty();
+ if (empty) {
+ imgCache = QPixmap();
+ imgStyleCache = QPixmap();
+ } else if (richText) {
+ imgCache = richTextImage(false);
+ if (style != QFxText::Normal)
+ imgStyleCache = richTextImage(true); //### should use styleColor
+ } else {
+ imgCache = wrappedTextImage(false);
+ if (style != QFxText::Normal)
+ imgStyleCache = wrappedTextImage(true); //### should use styleColor
+ }
+ if (!empty)
+ switch (style) {
+ case QFxText::Outline:
+ drawOutline();
+ break;
+ case QFxText::Sunken:
+ drawOutline(-1);
+ break;
+ case QFxText::Raised:
+ drawOutline(1);
+ break;
+ default:
+ break;
+ }
+
+#if defined(QFX_RENDER_OPENGL)
+ tex.setImage(imgCache.toImage());
+#endif
+
+ imgDirty = false;
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxText::paintContents(QPainter &p)
+{
+ Q_D(QFxText);
+ d->checkImgCache();
+ if (d->imgCache.isNull())
+ return;
+
+ int w = width();
+ int h = height();
+
+ int x = 0;
+ int y = 0;
+
+ switch (d->hAlign) {
+ case AlignLeft:
+ x = 0;
+ break;
+ case AlignRight:
+ x = w - d->imgCache.width();
+ break;
+ case AlignHCenter:
+ x = (w - d->imgCache.width()) / 2;
+ break;
+ }
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->imgCache.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->imgCache.height()) / 2;
+ break;
+ }
+
+ bool needClip = !clip() && (d->imgCache.width() > width() ||
+ d->imgCache.height() > height());
+
+ if (needClip) {
+ p.save();
+ p.setClipRect(boundingRect());
+ }
+ p.drawPixmap(x, y, d->imgCache);
+ if (needClip)
+ p.restore();
+}
+
+#elif defined(QFX_RENDER_OPENGL2)
+void QFxText::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxText);
+ d->checkImgCache();
+ if (d->imgCache.isNull())
+ return;
+
+ int w = width();
+ int h = height();
+
+ float x = 0;
+ float y = 0;
+
+ switch (d->hAlign) {
+ case AlignLeft:
+ x = 0;
+ break;
+ case AlignRight:
+ x = w - d->imgCache.width();
+ break;
+ case AlignHCenter:
+ x = (w - d->imgCache.width()) / 2;
+ break;
+ }
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->imgCache.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->imgCache.height()) / 2;
+ break;
+ }
+
+ float widthV = d->imgCache.width();
+ float heightV = d->imgCache.height();
+
+ QGLShaderProgram *shader = p.useTextureShader();
+
+ GLfloat vertices[] = { x, y + heightV,
+ x + widthV, y + heightV,
+ x, y,
+ x + widthV, y };
+
+ GLfloat texVertices[] = { 0, 0,
+ 1, 0,
+ 0, 1,
+ 1, 1 };
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+}
+
+#elif defined(QFX_RENDER_OPENGL)
+void QFxText::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxText);
+ d->checkImgCache();
+ if (d->imgCache.isNull())
+ return;
+
+ int w = width();
+ int h = height();
+
+ float x = 0;
+ float y = 0;
+
+ switch (d->hAlign) {
+ case AlignLeft:
+ x = 0;
+ break;
+ case AlignRight:
+ x = w - d->imgCache.width();
+ break;
+ case AlignHCenter:
+ x = (w - d->imgCache.width()) / 2;
+ break;
+ }
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->imgCache.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->imgCache.height()) / 2;
+ break;
+ }
+
+ float widthV = d->imgCache.width();
+ float heightV = d->imgCache.height();
+
+ GLfloat vertices[] = { x, y + heightV,
+ x + widthV, y + heightV,
+ x, y,
+ x + widthV, y };
+
+ GLfloat texVertices[] = { 0, 0,
+ 1, 0,
+ 0, 1,
+ 1, 1 };
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(p.activeTransform.data());
+ glEnable(GL_TEXTURE_2D);
+ if (p.activeOpacity == 1.) {
+ GLint i = GL_REPLACE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ } else {
+ GLint i = GL_MODULATE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ glColor4f(1, 1, 1, p.activeOpacity);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texVertices);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+}
+
+#endif
+
+void QFxText::componentComplete()
+{
+ Q_D(QFxText);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::TextComponentComplete> cc;
+#endif
+ QFxItem::componentComplete();
+ if (d->dirty) {
+ d->updateSize();
+ d->dirty = false;
+ }
+}
+
+/*!
+ \overload
+ Handles the given mouse \a event.
+ */
+void QFxText::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxText);
+
+ if (!d->richText || !d->doc || d->control->anchorAt(event->pos()).isEmpty()) {
+ event->setAccepted(false);
+ d->activeLink = QString();
+ } else {
+ d->activeLink = d->control->anchorAt(event->pos());
+ }
+
+ // ### may malfunction if two of the same links are clicked & dragged onto each other)
+
+ if (!event->isAccepted())
+ QFxItem::mousePressEvent(event);
+
+}
+
+/*!
+ \overload
+ Handles the given mouse \a event.
+ */
+void QFxText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxText);
+
+ // ### confirm the link, and send a signal out
+ if (d->richText && d->doc && d->activeLink == d->control->anchorAt(event->pos()))
+ emit linkActivated(d->activeLink);
+ else
+ event->setAccepted(false);
+
+ if (!event->isAccepted())
+ QFxItem::mouseReleaseEvent(event);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxtext.h b/src/declarative/fx/qfxtext.h
new file mode 100644
index 0000000..99ab2be
--- /dev/null
+++ b/src/declarative/fx/qfxtext.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXT_H
+#define QFXTEXT_H
+
+#include <QtDeclarative/qfxitem.h>
+#include <QtDeclarative/qmlfont.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxTextPrivate;
+class Q_DECLARATIVE_EXPORT QFxText : public QFxItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(TextStyle)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QmlFont *font READ font)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(TextStyle style READ style WRITE setStyle)
+ Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor)
+ Q_PROPERTY(HAlignment hAlign READ hAlign WRITE setHAlign)
+ Q_PROPERTY(VAlignment vAlign READ vAlign WRITE setVAlign)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap)
+ Q_PROPERTY(Qt::TextElideMode elide READ elideMode WRITE setElideMode)
+ Q_PROPERTY(QString activeLink READ activeLink)
+ Q_CLASSINFO("DefaultProperty", "text")
+
+public:
+ QFxText(QFxItem *parent=0);
+ ~QFxText();
+
+ enum HAlignment { AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter };
+ enum VAlignment { AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter };
+ enum TextStyle { Normal,
+ Outline,
+ Raised,
+ Sunken };
+
+ QString text() const;
+ void setText(const QString &);
+
+ QmlFont *font();
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ TextStyle style() const;
+ void setStyle(TextStyle style);
+
+ QColor styleColor() const;
+ void setStyleColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ bool wrap() const;
+ void setWrap(bool w);
+
+ Qt::TextElideMode elideMode() const;
+ void setElideMode(Qt::TextElideMode);
+
+ QString activeLink() const;
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &p);
+#elif defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+#endif
+
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void textChanged(const QString &text);
+ void linkActivated(const QString &link);
+
+private Q_SLOTS:
+ //### should be in QFxTextPrivate?
+ void fontChanged();
+
+protected:
+ QFxText(QFxTextPrivate &dd, QFxItem *parent);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private:
+ Q_DISABLE_COPY(QFxText)
+ Q_DECLARE_PRIVATE(QFxText)
+};
+QML_DECLARE_TYPE(QFxText)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxtext_p.h b/src/declarative/fx/qfxtext_p.h
new file mode 100644
index 0000000..dfaef63
--- /dev/null
+++ b/src/declarative/fx/qfxtext_p.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXT_P_H
+#define QFXTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxitem.h"
+#include "qfxitem_p.h"
+#include "qml.h"
+#include <QtGui/qtextlayout.h>
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QTextLayout;
+class QTextDocument;
+class QTextControl;
+
+class QFxTextPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxText)
+public:
+ QFxTextPrivate()
+ : _font(0), color((QRgb)0), style(QFxText::Normal), imgDirty(true),
+ hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), elideMode(Qt::ElideNone),
+ dirty(false), wrap(false), richText(false), singleline(false), control(0), doc(0)
+ {
+ }
+
+ ~QFxTextPrivate()
+ {
+ delete _font;
+ }
+
+ void init()
+ {
+ }
+
+ void updateSize();
+ void checkImgCache();
+
+ void drawOutline();
+ void drawOutline(int yOffset);
+
+ QPixmap wrappedTextImage(bool drawStyle);
+ QPixmap richTextImage(bool drawStyle);
+ QSize setupTextLayout(QTextLayout *layout);
+
+ QString text;
+ QmlFont *font()
+ {
+ if (!_font) {
+ Q_Q(QFxText);
+ _font = new QmlFont;
+ QObject::connect(_font, SIGNAL(updated()), q, SLOT(fontChanged()));
+ }
+ return _font;
+ }
+
+ QmlFont *_font;
+ QColor color;
+ QFxText::TextStyle style;
+ QColor styleColor;
+ QString activeLink;
+ bool imgDirty;
+#if defined(QFX_RENDER_OPENGL)
+ GLTexture tex;
+#endif
+ QPixmap imgCache;
+ QPixmap imgStyleCache;
+ QFxText::HAlignment hAlign;
+ QFxText::VAlignment vAlign;
+ Qt::TextElideMode elideMode;
+ bool dirty;
+ bool wrap;
+ bool richText;
+ bool singleline;
+ QTextControl *control;
+ QTextDocument *doc;
+ QTextLayout layout;
+ QSize cachedLayoutSize;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp
new file mode 100644
index 0000000..5492aaa
--- /dev/null
+++ b/src/declarative/fx/qfxtextedit.cpp
@@ -0,0 +1,938 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qfxtextedit.h>
+#include "qfxtextedit_p.h"
+
+#include <private/qtextcontrol_p.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+#endif
+
+#include <qfxperf.h>
+#include "qfxevents_p.h"
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QGraphicsSceneMouseEvent>
+
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxTextEdit, TextEdit)
+
+/*!
+ \qmlclass TextEdit
+ \brief The TextEdit item allows you to add editable formatted text to a scene.
+
+ It can display both plain and rich text. For example:
+
+ \qml
+TextEdit {
+ id: edit
+ text: "<b>Hello</b> <i>World!</i>"
+ focus: true
+ focusable: true
+ font.family: "Helvetica"
+ font.size: 20
+ color: "blue"
+ width: 240
+}
+ \endqml
+
+ \image declarative-textedit.gif
+
+ \sa Text
+*/
+
+/*!
+ \internal
+ \class QFxTextEdit
+ \qmlclass TextEdit
+ \ingroup group_coreitems
+
+ \brief The QFxTextEdit class provides an editable formatted text item that you can add to a QFxView.
+
+ It can display both plain and rich text.
+
+ \image declarative-textedit.png
+
+ A QFxTextEdit object can be instantiated in Qml using the tag \c &lt;TextEdit&gt;.
+*/
+
+/*!
+ Constructs a new QFxTextEdit.
+*/
+QFxTextEdit::QFxTextEdit(QFxItem *parent)
+: QFxPaintedItem(*(new QFxTextEditPrivate), parent)
+{
+ Q_D(QFxTextEdit);
+ d->init();
+}
+
+/*!
+\internal
+*/
+QFxTextEdit::QFxTextEdit(QFxTextEditPrivate &dd, QFxItem *parent)
+ : QFxPaintedItem(dd, parent)
+{
+ Q_D(QFxTextEdit);
+ d->init();
+}
+
+QString QFxTextEdit::text() const
+{
+ Q_D(const QFxTextEdit);
+
+ if (d->richText)
+ return d->document->toHtml();
+ else
+ return d->document->toPlainText();
+}
+
+/*!
+ \qmlproperty font TextEdit::font
+
+ Set the TextEdit's font attributes. \c font.size sets the font's point size.
+*/
+
+/*!
+ \qmlproperty string TextEdit::text
+ \default
+
+ The text to display. If the text format is AutoText the text edit will
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+*/
+
+/*!
+ \property QFxTextEdit::text
+ \brief the text edit's text
+
+ If the text format is set to AutoText the text edit will try to
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \sa textFormat
+*/
+
+void QFxTextEdit::setText(const QString &text)
+{
+ Q_D(QFxTextEdit);
+ if (QFxTextEdit::text() == text)
+ return;
+ d->text = text;
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
+ if (d->richText) {
+ d->control->setHtml(text);
+ } else {
+ d->control->setPlainText(text);
+ }
+ q_textChanged();
+ updateSize();
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::textFormat
+
+ The way the text property should be displayed.
+
+ Supported text formats are \c AutoText, \c PlainText and \c RichText.
+
+ The default is AutoText. If the text format is AutoText the text edit
+ edit will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \table
+ \row
+ \o
+ \qml
+VerticalLayout {
+ TextEdit {
+ font.size: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.size: 24
+ textFormat: "RichText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.size: 24
+ textFormat: "PlainText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+
+/*!
+ \property QFxTextEdit::textFormat
+ \brief this property describes how the text set on the text edit
+ should be interpreted.
+
+ Valid values are \c AutoText, \c PlainText and \c RichText. The
+ default value is \c AutoText, meaning the text edit will attempt
+ to guess how the text should be interpreted using the
+ Qt::mightBeRichText() function.
+
+ \sa text
+*/
+
+QFxTextEdit::TextFormat QFxTextEdit::textFormat() const
+{
+ Q_D(const QFxTextEdit);
+ return d->format;
+}
+
+void QFxTextEdit::setTextFormat(TextFormat format)
+{
+ Q_D(QFxTextEdit);
+ if (format == d->format)
+ return;
+ bool wasRich = d->richText;
+ d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (wasRich && !d->richText) {
+ d->control->setPlainText(d->text);
+ updateSize();
+ } else if (!wasRich && d->richText) {
+ d->control->setHtml(d->text);
+ updateSize();
+ }
+ d->format = format;
+}
+
+/*!
+ \property QFxTextEdit::font
+ \brief the text edit's default font
+*/
+
+QmlFont *QFxTextEdit::font()
+{
+ Q_D(QFxTextEdit);
+ return &(d->font);
+}
+
+/*!
+ \qmlproperty color TextEdit::color
+
+ The text color.
+
+ \qml
+// green text using hexadecimal notation
+TextEdit { color: "#00FF00"; ... }
+
+// steelblue text using SVG color name
+TextEdit { color: "steelblue"; ... }
+ \endqml
+*/
+
+/*!
+ \property QFxTextEdit::color
+ \brief the text edit's default text color
+*/
+QColor QFxTextEdit::color() const
+{
+ Q_D(const QFxTextEdit);
+ return d->color;
+}
+
+void QFxTextEdit::setColor(const QColor &color)
+{
+ Q_D(QFxTextEdit);
+ if (d->color == color)
+ return;
+
+ clearCache();
+ d->color = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Text, color);
+ d->control->setPalette(pal);
+ update();
+}
+
+/*!
+ \qmlproperty color TextEdit::highlightColor
+
+ The text highlight color, used behind selections.
+*/
+
+/*!
+ \property QFxTextEdit::highlightColor
+ \brief the text edit's default text highlight color
+*/
+QColor QFxTextEdit::highlightColor() const
+{
+ Q_D(const QFxTextEdit);
+ return d->highlightColor;
+}
+
+void QFxTextEdit::setHighlightColor(const QColor &color)
+{
+ Q_D(QFxTextEdit);
+ if (d->highlightColor == color)
+ return;
+
+ clearCache();
+ d->highlightColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Highlight, color);
+ d->control->setPalette(pal);
+ update();
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::hAlign
+ \qmlproperty enumeration TextEdit::vAlign
+
+ Sets the horizontal and vertical alignment of the text within the TextEdit items
+ width and height. By default, the text is top-left aligned.
+
+ The valid values for \c hAlign are \c AlignLeft, \c AlignRight and
+ \c AlignHCenter. The valid values for \c vAlign are \c AlignTop, \c AlignBottom
+ and \c AlignVCenter.
+*/
+
+/*!
+ \property QFxTextEdit::hAlign
+ \brief the horizontal alignment of the text.
+
+ Valid values are \c AlignLeft, \c AlignRight, and \c AlignHCenter. The default value is \c AlignLeft.
+*/
+QFxTextEdit::HAlignment QFxTextEdit::hAlign() const
+{
+ Q_D(const QFxTextEdit);
+ return d->hAlign;
+}
+
+void QFxTextEdit::setHAlign(QFxTextEdit::HAlignment alignment)
+{
+ Q_D(QFxTextEdit);
+ if (alignment == d->hAlign)
+ return;
+ d->hAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+}
+
+/*!
+ \property QFxTextEdit::vAlign
+ \brief the vertical alignment of the text.
+
+ Valid values are \c AlignTop, \c AlignBottom, and \c AlignVCenter. The default value is \c AlignTop.
+*/
+QFxTextEdit::VAlignment QFxTextEdit::vAlign() const
+{
+ Q_D(const QFxTextEdit);
+ return d->vAlign;
+}
+
+void QFxTextEdit::setVAlign(QFxTextEdit::VAlignment alignment)
+{
+ Q_D(QFxTextEdit);
+ if (alignment == d->vAlign)
+ return;
+ d->vAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+}
+
+bool QFxTextEdit::wrap() const
+{
+ Q_D(const QFxTextEdit);
+ return d->wrap;
+}
+
+/*!
+ \qmlproperty bool TextEdit::wrap
+
+ Set this property to wrap the text to the TextEdit item's width.
+ The text will only wrap if an explicit width has been set.
+
+ Wrapping is done on word boundaries (i.e. it is a "word-wrap"). Wrapping is off by default.
+*/
+
+/*!
+ \property QFxTextEdit::wrap
+ \brief If true the text edit wraps text based on the width of the
+ text edit.
+*/
+void QFxTextEdit::setWrap(bool w)
+{
+ Q_D(QFxTextEdit);
+ if (w == d->wrap)
+ return;
+ d->wrap = w;
+ d->updateDefaultTextOption();
+ updateSize();
+}
+
+/*!
+ \property QFxTextEdit::cursorVisible
+ \brief If true the text edit shows a cursor.
+
+ This property is set and unset when the text edit gets focus, but it can also
+ be set directly (useful, for example, if a KeyProxy might forward keys to it).
+*/
+bool QFxTextEdit::isCursorVisible() const
+{
+ Q_D(const QFxTextEdit);
+ return d->cursorVisible;
+}
+
+void QFxTextEdit::setCursorVisible(bool on)
+{
+ Q_D(QFxTextEdit);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
+ if (!on && !d->preserveSelection)
+ d->control->setCursorIsFocusIndicator(true);
+ d->control->processEvent(&focusEvent, QPointF(0, 0));
+}
+
+/*!
+ \qmlproperty bool TextEdit::focusOnPress
+
+ Whether the TextEdit should gain focus on a mouse press. By default this is
+ set to false;
+*/
+bool QFxTextEdit::focusOnPress() const
+{
+ Q_D(const QFxTextEdit);
+ return d->focusOnPress;
+}
+
+void QFxTextEdit::setFocusOnPress(bool on)
+{
+ Q_D(QFxTextEdit);
+ if (d->focusOnPress == on)
+ return;
+ d->focusOnPress = on;
+}
+
+/*!
+ \qmlproperty bool TextEdit::preserveSelection
+
+ Whether the TextEdit should keep the selection visible when it loses focus to another
+ item in the scene. By default this is set to true;
+*/
+bool QFxTextEdit::preserveSelection() const
+{
+ Q_D(const QFxTextEdit);
+ return d->preserveSelection;
+}
+
+void QFxTextEdit::setPreserveSelection(bool on)
+{
+ Q_D(QFxTextEdit);
+ if (d->preserveSelection == on)
+ return;
+ d->preserveSelection = on;
+}
+
+qreal QFxTextEdit::textMargin() const
+{
+ Q_D(const QFxTextEdit);
+ return d->textMargin;
+}
+
+void QFxTextEdit::setTextMargin(qreal margin)
+{
+ Q_D(QFxTextEdit);
+ if (d->textMargin == margin)
+ return;
+ d->textMargin = margin;
+ d->document->setDocumentMargin(d->textMargin);
+}
+
+void QFxTextEdit::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width())
+ updateSize();
+ QFxPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+/*!
+ \internal
+*/
+void QFxTextEdit::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << propertyInfo();
+ QFxPaintedItem::dump(depth);
+}
+
+/*!
+ \internal
+*/
+QString QFxTextEdit::propertyInfo() const
+{
+ Q_D(const QFxTextEdit);
+ return QChar(QLatin1Char('\"')) + d->text + QChar(QLatin1Char('\"'));
+}
+
+/*!
+ Ensures any delayed caching or data loading the class
+ needs to performed is complete.
+*/
+void QFxTextEdit::componentComplete()
+{
+ Q_D(QFxTextEdit);
+ QFxPaintedItem::componentComplete();
+ if (d->dirty) {
+ updateSize();
+ d->dirty = false;
+ }
+}
+
+/*!
+ \qmlproperty bool TextEdit::readOnly
+
+ Whether the user an interact with the TextEdit item. If this
+ property is set to true the text cannot be edited by user interaction.
+
+ By default this property is false.
+*/
+
+/*!
+ \property QFxTextEdit::readOnly
+ \brief If this property is true the text can not be edited by user interaction.
+
+ Changing this property will modify the text interaction flags. If
+ you require more specific control about how user interaction
+ with the text edit is handled, use setTextInteractionFlags() instead.
+
+ \sa setTextInteractionFlags()
+*/
+void QFxTextEdit::setReadOnly(bool r)
+{
+ Q_D(QFxTextEdit);
+
+ Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
+ if (r) {
+ flags = Qt::TextSelectableByMouse;
+ } else {
+ flags = Qt::TextEditorInteraction;
+ }
+ d->control->setTextInteractionFlags(flags);
+ if (!r)
+ d->control->moveCursor(QTextCursor::End);
+}
+
+bool QFxTextEdit::isReadOnly() const
+{
+ Q_D(const QFxTextEdit);
+ return !(d->control->textInteractionFlags() & Qt::TextEditable);
+}
+
+/*!
+ Sets how the text edit should interact with user input to the given
+ \a flags.
+*/
+void QFxTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
+{
+ Q_D(QFxTextEdit);
+ d->control->setTextInteractionFlags(flags);
+}
+
+/*!
+ Returns the flags specifying how the text edit should interact
+ with user input.
+*/
+Qt::TextInteractionFlags QFxTextEdit::textInteractionFlags() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->textInteractionFlags();
+}
+
+/*!
+ Returns the cursor for the point at the given \a pos on the
+ text edit.
+*/
+QTextCursor QFxTextEdit::cursorForPosition(const QPoint &pos) const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->cursorForPosition(pos);
+}
+
+/*!
+ Returns the rectangle where the given text \a cursor is rendered
+ within the text edit.
+*/
+QRect QFxTextEdit::cursorRect(const QTextCursor &cursor) const
+{
+ Q_D(const QFxTextEdit);
+ if (cursor.isNull())
+ return QRect();
+
+ return d->control->cursorRect(cursor).toRect();
+}
+
+/*!
+ Returns the rectangle where the text cursor is rendered
+ within the text edit.
+*/
+QRect QFxTextEdit::cursorRect() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->cursorRect().toRect();
+}
+
+
+/*!
+ Sets the text cursor for the text edit to the given \a cursor.
+*/
+void QFxTextEdit::setTextCursor(const QTextCursor &cursor)
+{
+ Q_D(QFxTextEdit);
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ Returns the text cursor for the text edit.
+*/
+QTextCursor QFxTextEdit::textCursor() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->textCursor();
+}
+
+/*!
+Moves the cursor by performing the given \a operation.
+
+If \a mode is QTextCursor::KeepAnchor, the cursor selects the text it moves over. This is the same effect that the user achieves when they hold down the Shift key and move the cursor with the cursor keys.
+*/
+void QFxTextEdit::moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode)
+{
+ Q_D(QFxTextEdit);
+ d->control->moveCursor(operation, mode);
+}
+
+/*!
+\overload
+Handles the given \a event.
+*/
+bool QFxTextEdit::event(QEvent *event)
+{
+ Q_D(QFxTextEdit);
+ if (event->type() == QEvent::ShortcutOverride) {
+ d->control->processEvent(event, QPointF(0, 0));
+ return true;
+ }
+ return QFxPaintedItem::event(event);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QFxTextEdit::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QFxTextEdit);
+ //### experiment with allowing 'overrides' to key events
+ QFxKeyEvent ke(*event);
+ emit keyPress(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (event->isAccepted())
+ return;
+
+ QTextCursor c = textCursor();
+ QTextCursor::MoveOperation op = QTextCursor::NoMove;
+ if (event == QKeySequence::MoveToNextChar) {
+ op = QTextCursor::Right;
+ } else if (event == QKeySequence::MoveToPreviousChar) {
+ op = QTextCursor::Left;
+ } else if (event == QKeySequence::MoveToNextWord) {
+ op = QTextCursor::WordRight;
+ } else if (event == QKeySequence::MoveToPreviousWord) {
+ op = QTextCursor::WordLeft;
+ } else if (event == QKeySequence::MoveToNextLine) {
+ op = QTextCursor::Down;
+ } else if (event == QKeySequence::MoveToPreviousLine) {
+ op = QTextCursor::Up;
+ }
+
+ if (op != QTextCursor::NoMove && !c.movePosition(op))
+ event->ignore();
+ else
+ d->control->processEvent(event, QPointF(0, 0));
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QFxTextEdit::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QFxTextEdit);
+ //### experiment with allowing 'overrides' to key events
+ QFxKeyEvent ke(*event);
+ emit keyRelease(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (event->isAccepted())
+ return;
+
+ d->control->processEvent(event, QPointF(0, 0));
+}
+
+/*!
+ \overload
+ Handles changing of the focus property. Focus is applied to the control
+ even if the edit does not have active focus. This is because things
+ like KeyProxy can give the behavior of focus even when activeFocus isn't
+ true.
+*/
+void QFxTextEdit::focusChanged(bool hasFocus)
+{
+ setCursorVisible(hasFocus);
+}
+
+/*!
+ Causes all text to be selected.
+*/
+void QFxTextEdit::selectAll()
+{
+ Q_D(QFxTextEdit);
+ d->control->selectAll();
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QFxTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextEdit);
+ if (d->focusOnPress)
+ setFocus(true);
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QFxTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QFxTextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QFxPaintedItem::mouseDoubleClickEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QFxTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given input method \a event.
+*/
+void QFxTextEdit::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QFxTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+}
+
+/*!
+\overload
+Returns the value of the given \a property.
+*/
+QVariant QFxTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->inputMethodQuery(property);
+}
+
+/*!
+Draws the contents of the text edit using the given \a painter within
+the given \a bounds.
+*/
+void QFxTextEdit::drawContents(QPainter *painter, const QRect &bounds)
+{
+ Q_D(QFxTextEdit);
+
+ painter->setRenderHint(QPainter::TextAntialiasing, true);
+
+ d->control->drawContents(painter, bounds);
+}
+
+/*!
+This signal is emitted when the font of the item changes.
+*/
+void QFxTextEdit::fontChanged()
+{
+ Q_D(QFxTextEdit);
+ clearCache();
+ d->document->setDefaultFont(d->font.font());
+ updateSize();
+ emit update();
+}
+
+void QFxTextEdit::updateImgCache(const QRectF &r)
+{
+ dirtyCache(r.toRect());
+ emit update();
+}
+
+void QFxTextEditPrivate::init()
+{
+ Q_Q(QFxTextEdit);
+
+ q->setSmooth(true);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setOptions(QFxTextEdit::AcceptsInputMethods | QFxTextEdit::SimpleItem
+ | QFxTextEdit::HasContents | QFxTextEdit::MouseEvents);
+
+ QObject::connect(&font, SIGNAL(updated()), q, SLOT(fontChanged()));
+
+ control = new QTextControl(q);
+
+ QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
+
+ QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
+
+ document = control->document();
+ document->setDefaultFont(font.font());
+ document->setDocumentMargin(textMargin);
+ document->setUndoRedoEnabled(false); // flush undo buffer.
+ document->setUndoRedoEnabled(true);
+ updateDefaultTextOption();
+}
+
+void QFxTextEdit::q_textChanged()
+{
+ if (!widthValid())
+ updateSize(); //### optimize: we get 3 calls to updateSize every time a letter is typed
+ emit textChanged(text());
+}
+
+//### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
+// need to do all the calculations each time
+void QFxTextEdit::updateSize()
+{
+ Q_D(QFxTextEdit);
+ if (isComponentComplete()) {
+ QFontMetrics fm = QFontMetrics(d->font.font());
+ int dy = height();
+ // ### assumes that if the width is set, the text will fill to edges
+ // ### (unless wrap is false, then clipping will occur)
+ if (widthValid())
+ d->document->setTextWidth(width());
+ dy -= (int)d->document->size().height();
+
+ int yoff = 0;
+ if (heightValid()) {
+ if (d->vAlign == AlignBottom)
+ yoff = dy;
+ else if (d->vAlign == AlignVCenter)
+ yoff = dy/2;
+ }
+ setBaselineOffset(fm.ascent() + yoff + d->textMargin);
+ if (!widthValid()) {
+ int newWidth = (int)d->document->idealWidth();
+ d->document->setTextWidth(newWidth); // ### QTextDoc> Alignment will not work unless textWidth is set
+ setImplicitWidth(newWidth);
+ }
+ if (!heightValid()) {
+ if (d->text.isEmpty()) {
+ setImplicitHeight(fm.height());
+ } else {
+ setImplicitHeight((int)d->document->size().height());
+ }
+ }
+ setContentsSize(QSize(width(), height()));
+ } else {
+ d->dirty = true;
+ }
+ emit update();
+}
+
+void QFxTextEditPrivate::updateDefaultTextOption()
+{
+ QTextOption opt = document->defaultTextOption();
+ int oldAlignment = opt.alignment();
+ opt.setAlignment((Qt::Alignment)(int)(hAlign | vAlign));
+
+ QTextOption::WrapMode oldWrapMode = opt.wrapMode();
+
+ if (wrap)
+ opt.setWrapMode(QTextOption::WordWrap);
+ else
+ opt.setWrapMode(QTextOption::NoWrap);
+
+ if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
+ return;
+ document->setDefaultTextOption(opt);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxtextedit.h b/src/declarative/fx/qfxtextedit.h
new file mode 100644
index 0000000..b761a1b
--- /dev/null
+++ b/src/declarative/fx/qfxtextedit.h
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXTEDIT_H
+#define QFXTEXTEDIT_H
+
+#include <QtDeclarative/qfxtext.h>
+#include <QtDeclarative/qfxpainteditem.h>
+
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qtextoption.h>
+#include <QtGui/qtextcursor.h>
+#include <QtGui/qtextformat.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+/*!
+WARNING: SHORT TERM CLASS. INTENDED TO MERGE INTO QFxTextItem
+*/
+class QFxTextEditPrivate;
+class Q_DECLARATIVE_EXPORT QFxTextEdit : public QFxPaintedItem
+{
+ Q_OBJECT
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(TextFormat)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor)
+ Q_PROPERTY(QmlFont * font READ font)
+ Q_PROPERTY(HAlignment hAlign READ hAlign WRITE setHAlign)
+ Q_PROPERTY(VAlignment vAlign READ vAlign WRITE setVAlign)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap)
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible)
+ Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress)
+ Q_PROPERTY(bool preserveSelection READ preserveSelection WRITE setPreserveSelection)
+ Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin)
+
+public:
+ QFxTextEdit(QFxItem *parent=0);
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter
+ };
+
+ enum VAlignment {
+ AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter
+ };
+
+ enum TextFormat {
+ AutoText,
+ PlainText,
+ RichText,
+ };
+
+ QString text() const;
+ void setText(const QString &);
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ // leave in, have affect the default text
+ QmlFont *font();
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor highlightColor() const;
+ void setHighlightColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ bool wrap() const;
+ void setWrap(bool w);
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool on);
+
+ bool preserveSelection() const;
+ void setPreserveSelection(bool on);
+
+ qreal textMargin() const;
+ void setTextMargin(qreal margin);
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+ virtual void componentComplete();
+
+ /* FROM EDIT */
+ void setReadOnly(bool);
+ bool isReadOnly() const;
+
+ void setTextInteractionFlags(Qt::TextInteractionFlags flags);
+ Qt::TextInteractionFlags textInteractionFlags() const;
+
+ QTextCursor cursorForPosition(const QPoint &pos) const;
+ QRect cursorRect(const QTextCursor &cursor) const;
+ QRect cursorRect() const;
+
+ void setTextCursor(const QTextCursor &cursor);
+ QTextCursor textCursor() const;
+
+ void moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor);
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+Q_SIGNALS:
+ void textChanged(const QString &);
+ void cursorPositionChanged();
+
+public Q_SLOTS:
+ void selectAll();
+
+private Q_SLOTS:
+ void fontChanged();
+ void updateImgCache(const QRectF &rect);
+ void q_textChanged();
+
+private:
+ void updateSize();
+
+protected:
+ QFxTextEdit(QFxTextEditPrivate &dd, QFxItem *parent);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ bool event(QEvent *);
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+
+ void focusChanged(bool);
+
+ // mouse filter?
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+
+ void inputMethodEvent(QInputMethodEvent *e);
+
+ void drawContents(QPainter *, const QRect &);
+private:
+
+ friend class QmlFont;
+ Q_DISABLE_COPY(QFxTextEdit)
+ Q_DECLARE_PRIVATE(QFxTextEdit)
+};
+QML_DECLARE_TYPE(QFxTextEdit)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxtextedit_p.h b/src/declarative/fx/qfxtextedit_p.h
new file mode 100644
index 0000000..f733a4c
--- /dev/null
+++ b/src/declarative/fx/qfxtextedit_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXTEDIT_P_H
+#define QFXTEXTEDIT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfxitem.h"
+#include "qfxpainteditem_p.h"
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+class QTextLayout;
+class QTextDocument;
+class QTextControl;
+class QFxTextEditPrivate : public QFxPaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxTextEdit)
+
+public:
+ QFxTextEditPrivate()
+ : font(0), color("black"), imgDirty(true), hAlign(QFxTextEdit::AlignLeft), vAlign(QFxTextEdit::AlignTop),
+ dirty(false), wrap(false), richText(false), cursorVisible(false), focusOnPress(false), preserveSelection(true),
+ textMargin(0.0), format(QFxTextEdit::AutoText), document(0)
+ {
+ }
+
+ void init();
+
+ void updateDefaultTextOption();
+ void relayoutDocument();
+
+ QString text;
+ QmlFont font;
+ QColor color;
+ QColor highlightColor;
+ QString style;
+ QColor styleColor;
+ bool imgDirty;
+#if defined(QFX_RENDER_OPENGL)
+ GLTexture texture;
+#endif
+ QPixmap imgCache;
+ QPixmap imgStyleCache;
+ QFxTextEdit::HAlignment hAlign;
+ QFxTextEdit::VAlignment vAlign;
+ bool dirty;
+ bool wrap;
+ bool richText;
+ bool cursorVisible;
+ bool focusOnPress;
+ bool preserveSelection;
+ qreal textMargin;
+ QFxTextEdit::TextFormat format;
+ QTextDocument *document;
+ QTextControl *control;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxtransform.cpp b/src/declarative/fx/qfxtransform.cpp
new file mode 100644
index 0000000..a4c5d22
--- /dev/null
+++ b/src/declarative/fx/qfxtransform.cpp
@@ -0,0 +1,895 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include "private/qfxitem_p.h"
+#include "qfxtransform.h"
+#include <QtDeclarative/qmlinfo.h>
+
+#include <math.h>
+#ifndef M_PI
+
+QT_BEGIN_NAMESPACE
+#define M_PI 3.14159265358979323846
+#endif
+
+QML_DEFINE_NOCREATE_TYPE(QFxTransform);
+
+/*!
+ \qmlclass Transform
+ \brief A transformation.
+*/
+QFxTransform::QFxTransform(QObject *parent) :
+ QObject(parent)
+{
+}
+
+QFxTransform::~QFxTransform()
+{
+}
+
+bool QFxTransform::isIdentity() const
+{
+ return true;
+}
+
+QSimpleCanvas::Matrix QFxTransform::transform() const
+{
+ return QSimpleCanvas::Matrix();
+}
+
+void QFxTransform::update()
+{
+ QFxItem *item = qobject_cast<QFxItem *>(parent());
+ if (item)
+ item->updateTransform();
+}
+
+/*!
+ \qmlclass Axis
+ \brief A Axis object defines an axis that can be used for rotation or translation.
+
+ An axis is specified by 2 points in 3D space: a start point and
+ an end point. While technically the axis is the line running through these two points
+ (and thus many different sets of two points could define the same axis), the distance
+ between the points does matter for translation along an axis.
+
+ \image 3d-axis.png
+
+ \qml
+ Axis { startX: 20; startY: 0; endX: 40; endY: 60; endZ: 20 }
+ \endqml
+*/
+
+QML_DEFINE_TYPE(QFxAxis, Axis)
+
+QFxAxis::QFxAxis(QObject *parent)
+: QObject(parent), _startX(0), _startY(0), _endX(0), _endY(0), _endZ(0)
+{
+}
+
+QFxAxis::~QFxAxis()
+{
+}
+
+/*!
+ \qmlproperty real Axis::startX
+ \qmlproperty real Axis::startY
+
+ The start point of the axis. The z-position of the start point is assumed to be 0, and cannot
+ be changed.
+*/
+qreal QFxAxis::startX() const
+{
+ return _startX;
+}
+
+void QFxAxis::setStartX(qreal x)
+{
+ _startX = x;
+ emit updated();
+}
+
+qreal QFxAxis::startY() const
+{
+ return _startY;
+}
+
+void QFxAxis::setStartY(qreal y)
+{
+ _startY = y;
+ emit updated();
+}
+
+/*!
+ \qmlproperty real Axis::endX
+ \qmlproperty real Axis::endY
+ \qmlproperty real Axis::endZ
+
+ The end point of the axis.
+*/
+qreal QFxAxis::endX() const
+{
+ return _endX;
+}
+
+void QFxAxis::setEndX(qreal x)
+{
+ _endX = x;
+ emit updated();
+}
+
+qreal QFxAxis::endY() const
+{
+ return _endY;
+}
+
+void QFxAxis::setEndY(qreal y)
+{
+ _endY = y;
+ emit updated();
+}
+
+qreal QFxAxis::endZ() const
+{
+ return _endZ;
+}
+
+void QFxAxis::setEndZ(qreal z)
+{
+ _endZ = z;
+ emit updated();
+}
+
+/*!
+ \qmlclass Rotation
+ \brief A Rotation object provides a way to rotate an Item around a point.
+
+ The following example rotates a Rect around its interior point 25, 25:
+ \qml
+ Rect {
+ width: 100; height: 100
+ color: "blue"
+ transform: Rotation { originX: 25; originY: 25; angle: 45}
+ }
+ \endqml
+*/
+
+QFxRotation::QFxRotation(QObject *parent)
+: QFxTransform(parent), _originX(0), _originY(0), _angle(0), _dirty(true)
+{
+}
+
+QFxRotation::~QFxRotation()
+{
+}
+
+/*!
+ \qmlproperty real Rotation::originX
+ \qmlproperty real Rotation::originY
+
+ The point to rotate around.
+*/
+qreal QFxRotation::originX() const
+{
+ return _originX;
+}
+
+void QFxRotation::setOriginX(qreal ox)
+{
+ _originX = ox;
+ update();
+}
+
+qreal QFxRotation::originY() const
+{
+ return _originY;
+}
+
+void QFxRotation::setOriginY(qreal oy)
+{
+ _originY = oy;
+ update();
+}
+
+/*!
+ \qmlproperty real Rotation::angle
+
+ The angle, in degrees, to rotate.
+*/
+qreal QFxRotation::angle() const
+{
+ return _angle;
+}
+
+void QFxRotation::setAngle(qreal angle)
+{
+ if (_angle == angle)
+ return;
+ _angle = angle;
+ update();
+ emit angleChanged();
+}
+
+bool QFxRotation::isIdentity() const
+{
+ return (_angle == 0.);
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+QTransform QFxRotation::transform() const
+{
+ if (_dirty) {
+ _transform = QTransform();
+ _dirty = false;
+ _transform.translate(_originX, _originY);
+ _transform.rotate(_angle);
+ _transform.translate(-_originX, -_originY);
+ }
+ return _transform;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxRotation::transform() const
+{
+ if (_dirty) {
+ _transform = QMatrix4x4();
+ _dirty = false;
+ _transform.translate(_originX, _originY);
+ _transform.rotate(_angle, 0, 0, 1);
+ _transform.translate(-_originX, -_originY);
+ }
+ return _transform;
+}
+#endif
+
+void QFxRotation::update()
+{
+ _dirty = true;
+ QFxTransform::update();
+}
+
+QML_DEFINE_TYPE(QFxRotation, Rotation)
+
+/*!
+ \qmlclass Rotation3D
+ \brief A Rotation3D object provides a way to rotate an Item around an axis.
+
+ Here is an example of various rotations applied to an \l Image.
+ \snippet doc/src/snippets/declarative/rotation.qml 0
+
+ \image axisrotation.png
+*/
+
+QML_DEFINE_TYPE(QFxRotation3D,Rotation3D)
+
+QFxRotation3D::QFxRotation3D(QObject *parent)
+: QFxTransform(parent), _angle(0), _dirty(true)
+{
+ connect(&_axis, SIGNAL(updated()), this, SLOT(update()));
+}
+
+QFxRotation3D::~QFxRotation3D()
+{
+}
+
+/*!
+ \qmlproperty real Rotation3D::axis.startX
+ \qmlproperty real Rotation3D::axis.startY
+ \qmlproperty real Rotation3D::axis.endX
+ \qmlproperty real Rotation3D::axis.endY
+ \qmlproperty real Rotation3D::axis.endZ
+
+ A rotation axis is specified by 2 points in 3D space: a start point and
+ an end point. The z-position of the start point is assumed to be 0, and cannot
+ be changed.
+
+ \image 3d-rotation-axis.png
+
+ \sa Axis
+*/
+QFxAxis *QFxRotation3D::axis()
+{
+ return &_axis;
+}
+
+/*!
+ \qmlproperty real Rotation3D::angle
+
+ The angle, in degrees, to rotate around the specified axis.
+*/
+qreal QFxRotation3D::angle() const
+{
+ return _angle;
+}
+
+void QFxRotation3D::setAngle(qreal angle)
+{
+ _angle = angle;
+ update();
+}
+
+bool QFxRotation3D::isIdentity() const
+{
+ return (_angle == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX());
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+const qreal inv_dist_to_plane = 1. / 1024.;
+QTransform QFxRotation3D::transform() const
+{
+ if (_dirty) {
+ _transform = QTransform();
+
+ if (!isIdentity()) {
+ if (angle() != 0.) {
+ QTransform rotTrans;
+ rotTrans.translate(-_axis.startX(), -_axis.startY());
+ QTransform rotTrans2;
+ rotTrans2.translate(_axis.startX(), _axis.startY());
+
+ qreal rad = angle() * 2. * M_PI / 360.;
+ qreal c = ::cos(rad);
+ qreal s = ::sin(rad);
+
+ qreal x = _axis.endX() - _axis.startX();
+ qreal y = _axis.endY() - _axis.startY();
+ qreal z = _axis.endZ();
+
+ qreal len = x * x + y * y + z * z;
+ if (len != 1.) {
+ len = ::sqrt(len);
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+
+ QTransform rot(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane,
+ y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane,
+ 0, 0, 1);
+
+ _transform *= rotTrans;
+ _transform *= rot;
+ _transform *= rotTrans2;
+ }
+ }
+
+ _dirty = false;
+ }
+
+ return _transform;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxRotation3D::transform() const
+{
+ if (_dirty) {
+ _dirty = false;
+ _transform = QMatrix4x4();
+
+ if (!isIdentity()) {
+ if (angle() != 0.) {
+ qreal x = _axis.endX() - _axis.startX();
+ qreal y = _axis.endY() - _axis.startY();
+ qreal z = _axis.endZ();
+
+ _transform.translate(_axis.startX(), _axis.startY(), 0);
+ _transform.rotate(angle(), x, y, z);
+ _transform.translate(-_axis.startX(), -_axis.startY(), 0);
+ }
+ }
+ }
+
+ return _transform;
+}
+#endif
+
+void QFxRotation3D::update()
+{
+ _dirty = true;
+ QFxTransform::update();
+}
+
+/*!
+ \internal
+ \qmlclass Translation3D
+ \brief A Translation3D object provides a way to move an Item along an axis.
+
+ The following example translates the image to 10, 3.
+ \qml
+Image {
+ source: "logo.png"
+ transform: [
+ Translation3D {
+ axis.startX: 0
+ axis.startY: 0
+ axis.endX: 1
+ axis.endY: .3
+ distance: 10
+ }
+ ]
+}
+ \endqml
+*/
+
+QML_DEFINE_TYPE(QFxTranslation3D,Translation3D)
+
+QFxTranslation3D::QFxTranslation3D(QObject *parent)
+: QFxTransform(parent), _distance(0), _dirty(true)
+{
+ connect(&_axis, SIGNAL(updated()), this, SLOT(update()));
+}
+
+QFxTranslation3D::~QFxTranslation3D()
+{
+}
+
+/*!
+ \qmlproperty real Translation3D::axis.startX
+ \qmlproperty real Translation3D::axis.startY
+ \qmlproperty real Translation3D::axis.endX
+ \qmlproperty real Translation3D::axis.endY
+ \qmlproperty real Translation3D::axis.endZ
+
+ A translation axis is specified by 2 points in 3D space: a start
+ point and an end point. The z-position of the start point is assumed
+ to be 0, and cannot be changed. Changing the z-position of the end
+ point is only valid when running under OpenGL.
+
+ \sa Axis
+*/
+QFxAxis *QFxTranslation3D::axis()
+{
+ return &_axis;
+}
+
+/*!
+ \qmlproperty real Translation3D::distance
+
+ The distance to translate along the specified axis. distance is a
+ multiplier; in the example below, a distance of 1 would translate to
+ 100, 50, while a distance of 0.5 would translate to 50, 25.
+
+ \qml
+ Translation3D { axis.startX: 0; axis.startY: 0; axis.endX: 100; axis.endY: 50 }
+ \endqml
+*/
+qreal QFxTranslation3D::distance() const
+{
+ return _distance;
+}
+
+void QFxTranslation3D::setDistance(qreal distance)
+{
+ _distance = distance;
+ update();
+}
+
+bool QFxTranslation3D::isIdentity() const
+{
+ return (_distance == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX());
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+QTransform QFxTranslation3D::transform() const
+{
+ if (_dirty) {
+ _transform = QTransform();
+
+ if (!isIdentity()) {
+ if (distance() != 0.) {
+ QTransform trans;
+ trans.translate((_axis.endX() - _axis.startX()) * distance(),
+ (_axis.endY() - _axis.startY()) * distance());
+ _transform *= trans;
+ }
+ }
+
+ _dirty = false;
+ }
+
+ return _transform;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxTranslation3D::transform() const
+{
+ if (_dirty) {
+ _dirty = false;
+ _transform = QMatrix4x4();
+
+ if (!isIdentity()) {
+ if (distance() != 0.)
+ _transform.translate((_axis.endX() - _axis.startX()) * distance(),
+ (_axis.endY() - _axis.startY()) * distance(),
+ (_axis.endZ()) * distance());
+
+ }
+ }
+
+ return _transform;
+}
+#endif
+
+void QFxTranslation3D::update()
+{
+ _dirty = true;
+
+#if !defined(QFX_RENDER_OPENGL)
+ if (_axis.endZ() != 0. && distance() != 0.) {
+ qmlInfo(this) << "QTransform cannot translate along Z-axis.";
+ }
+#endif
+
+ QFxTransform::update();
+}
+
+/*!
+ \internal
+ \qmlclass Perspective
+ \brief A Perspective object specifies a perspective transformation.
+
+ A Perspective transform only affects an item when running under
+ OpenGL. When running under software rasterization it has no effect.
+*/
+
+QML_DEFINE_TYPE(QFxPerspective,Perspective)
+
+QFxPerspective::QFxPerspective(QObject *parent)
+ : QFxTransform(parent)
+{
+}
+
+QFxPerspective::~QFxPerspective()
+{
+}
+
+#if defined(QFX_RENDER_OPENGL)
+bool QFxPerspective::isIdentity() const
+{
+ return false;
+}
+
+QMatrix4x4 QFxPerspective::transform() const
+{
+ QMatrix4x4 rv;
+ rv.translate(_x, _y);
+ rv.perspective(_angle, _aspect, 1, 1024 * 1024);
+ rv.translate(-_x, -_y, -1);
+ rv.scale(1, 1, 1. / _scale);
+
+ return rv;
+}
+#endif
+
+/*!
+ \qmlproperty real Perspective::angle
+*/
+
+/*!
+ \qmlproperty real Perspective::aspect
+*/
+
+/*!
+ \qmlproperty real Perspective::x
+*/
+
+/*!
+ \qmlproperty real Perspective::y
+*/
+
+/*!
+ \qmlproperty real Perspective::scale
+*/
+
+/*!
+ \qmlclass Squish
+ \brief A Squish object allows you to distort an item's appearance by 'squishing' it.
+
+ Conceptually, a Squish works by allowing you to move the four corners of an item,
+ and distorting the item to fit into the newly created polygon.
+
+ \image squish-transform.png
+
+ Here is an example of various \l Image squishes.
+ \qml
+ Rect {
+ id: Screen
+ width: 360; height: 80
+ color: "white"
+
+ HorizontalLayout {
+ margin: 10
+ spacing: 10
+ Image { source: "qt.png" }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:0; topLeftY:0
+ topRightX:50; topRightY:10
+ bottomLeftX:0; bottomLeftY:60
+ bottomRightX: 60; bottomRightY:60
+ }
+ }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:0; topLeftY:0
+ topRightX:50; topRightY:0
+ bottomLeftX:10; bottomLeftY:50
+ bottomRightX: 60; bottomRightY:60
+ }
+ }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:0; topLeftY:10
+ topRightX:60; topRightY:10
+ bottomLeftX:0; bottomLeftY:50
+ bottomRightX: 60; bottomRightY:50
+ }
+ }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:10; topLeftY:0
+ topRightX:50; topRightY:0
+ bottomLeftX:10; bottomLeftY:60
+ bottomRightX: 50; bottomRightY:60
+ }
+ }
+ }
+ }
+ \endqml
+
+ \image squish.png
+*/
+QML_DEFINE_TYPE(QFxSquish,Squish)
+
+QFxSquish::QFxSquish(QObject *parent)
+ : QFxTransform(parent)
+{
+}
+
+QFxSquish::~QFxSquish()
+{
+}
+
+/*!
+ \qmlproperty real Squish::x
+ \qmlproperty real Squish::y
+ \qmlproperty real Squish::width
+ \qmlproperty real Squish::height
+
+ This is usually set to the original geometry of the item being squished.
+*/
+qreal QFxSquish::x() const
+{
+ return p.x();
+}
+
+void QFxSquish::setX(qreal v)
+{
+ p.setX(v);
+ update();
+}
+
+qreal QFxSquish::y() const
+{
+ return p.y();
+}
+
+void QFxSquish::setY(qreal v)
+{
+ p.setY(v);
+ update();
+}
+
+qreal QFxSquish::width() const
+{
+ return s.width();
+}
+
+void QFxSquish::setWidth(qreal v)
+{
+ s.setWidth(v);
+ update();
+}
+
+qreal QFxSquish::height() const
+{
+ return s.height();
+}
+
+void QFxSquish::setHeight(qreal v)
+{
+ s.setHeight(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::topLeftX
+ \qmlproperty real Squish::topLeftY
+
+ The top left point for the squish.
+*/
+qreal QFxSquish::topLeft_x() const
+{
+ return p1.x();
+}
+
+void QFxSquish::settopLeft_x(qreal v)
+{
+ p1.setX(v);
+ update();
+}
+
+qreal QFxSquish::topLeft_y() const
+{
+ return p1.y();
+}
+
+void QFxSquish::settopLeft_y(qreal v)
+{
+ p1.setY(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::topRightX
+ \qmlproperty real Squish::topRightY
+
+ The top right point for the squish.
+*/
+qreal QFxSquish::topRight_x() const
+{
+ return p2.x();
+}
+
+void QFxSquish::settopRight_x(qreal v)
+{
+ p2.setX(v);
+ update();
+}
+
+qreal QFxSquish::topRight_y() const
+{
+ return p2.y();
+}
+
+void QFxSquish::settopRight_y(qreal v)
+{
+ p2.setY(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::bottomLeftX
+ \qmlproperty real Squish::bottomLeftY
+
+ The bottom left point for the squish.
+*/
+qreal QFxSquish::bottomLeft_x() const
+{
+ return p3.x();
+}
+
+void QFxSquish::setbottomLeft_x(qreal v)
+{
+ p3.setX(v);
+ update();
+}
+
+qreal QFxSquish::bottomLeft_y() const
+{
+ return p3.y();
+}
+
+void QFxSquish::setbottomLeft_y(qreal v)
+{
+ p3.setY(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::bottomRightX
+ \qmlproperty real Squish::bottomRightY
+
+ The bottom right point for the squish.
+*/
+qreal QFxSquish::bottomRight_x() const
+{
+ return p4.x();
+}
+
+void QFxSquish::setbottomRight_x(qreal v)
+{
+ p4.setX(v);
+ update();
+}
+
+qreal QFxSquish::bottomRight_y() const
+{
+ return p4.y();
+}
+
+void QFxSquish::setbottomRight_y(qreal v)
+{
+ p4.setY(v);
+ update();
+}
+
+bool QFxSquish::isIdentity() const
+{
+ return false;
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+QTransform QFxSquish::transform() const
+{
+ QPolygonF poly;
+ poly << p << QPointF(p.x() + s.width(), p.y()) << QPointF(p.x() + s.width(), p.y() + s.height()) << QPointF(p.x(), p.y() + s.height());
+ QPolygonF poly2;
+ poly2 << p1 << p2 << p4 << p3;
+
+ QTransform t;
+ QTransform::quadToQuad(poly, poly2, t);
+ return t;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxSquish::transform() const
+{
+ QPolygonF poly;
+ poly << p << QPointF(p.x() + s.width(), p.y()) << QPointF(p.x() + s.width(), p.y() + s.height()) << QPointF(p.x(), p.y() + s.height());
+ QPolygonF poly2;
+ poly2 << p1 << p2 << p4 << p3;
+
+ QTransform t;
+ QMatrix4x4 rv;
+ if (QTransform::quadToQuad(poly, poly2, t))
+ rv = QMatrix4x4(t);
+
+ return rv;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxtransform.h b/src/declarative/fx/qfxtransform.h
new file mode 100644
index 0000000..7be8adc
--- /dev/null
+++ b/src/declarative/fx/qfxtransform.h
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTRANSFORM_H
+#define QFXTRANSFORM_H
+
+#include <QtCore/QObject>
+#include <QtGui/QTransform>
+#if defined(QFX_RENDER_OPENGL)
+#include <QtGui/qmatrix4x4.h>
+#endif
+#include <QtDeclarative/qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QFxTransform : public QObject
+{
+ Q_OBJECT
+public:
+ QFxTransform(QObject *parent=0);
+ ~QFxTransform();
+
+ void update();
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+};
+QML_DECLARE_TYPE(QFxTransform)
+
+class Q_DECLARATIVE_EXPORT QFxAxis : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX)
+ Q_PROPERTY(qreal startY READ startY WRITE setStartY)
+ Q_PROPERTY(qreal endX READ endX WRITE setEndX)
+ Q_PROPERTY(qreal endY READ endY WRITE setEndY)
+ Q_PROPERTY(qreal endZ READ endZ WRITE setEndZ)
+public:
+ QFxAxis(QObject *parent=0);
+ ~QFxAxis();
+
+ qreal startX() const;
+ void setStartX(qreal);
+
+ qreal startY() const;
+ void setStartY(qreal);
+
+ qreal endX() const;
+ void setEndX(qreal);
+
+ qreal endY() const;
+ void setEndY(qreal);
+
+ qreal endZ() const;
+ void setEndZ(qreal);
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ qreal _startX;
+ qreal _startY;
+ qreal _endX;
+ qreal _endY;
+ qreal _endZ;
+};
+QML_DECLARE_TYPE(QFxAxis)
+
+class Q_DECLARATIVE_EXPORT QFxRotation : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal originX READ originX WRITE setOriginX)
+ Q_PROPERTY(qreal originY READ originY WRITE setOriginY)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged())
+public:
+ QFxRotation(QObject *parent=0);
+ ~QFxRotation();
+
+ qreal originX() const;
+ void setOriginX(qreal);
+
+ qreal originY() const;
+ void setOriginY(qreal);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+Q_SIGNALS:
+ void angleChanged();
+
+private Q_SLOTS:
+ void update();
+private:
+ qreal _originX;
+ qreal _originY;
+ qreal _angle;
+
+ mutable bool _dirty;
+ mutable QSimpleCanvas::Matrix _transform;
+};
+QML_DECLARE_TYPE(QFxRotation)
+
+class Q_DECLARATIVE_EXPORT QFxRotation3D : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxAxis *axis READ axis)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle)
+public:
+ QFxRotation3D(QObject *parent=0);
+ ~QFxRotation3D();
+
+ QFxAxis *axis();
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+private Q_SLOTS:
+ void update();
+private:
+ QFxAxis _axis;
+ qreal _angle;
+
+ mutable bool _dirty;
+ mutable QSimpleCanvas::Matrix _transform;
+};
+QML_DECLARE_TYPE(QFxRotation3D)
+
+class Q_DECLARATIVE_EXPORT QFxTranslation3D : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxAxis *axis READ axis)
+ Q_PROPERTY(qreal distance READ distance WRITE setDistance)
+public:
+ QFxTranslation3D(QObject *parent=0);
+ ~QFxTranslation3D();
+
+ QFxAxis *axis();
+
+ qreal distance() const;
+ void setDistance(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+private Q_SLOTS:
+ void update();
+private:
+ QFxAxis _axis;
+ qreal _distance;
+
+ mutable bool _dirty;
+ mutable QSimpleCanvas::Matrix _transform;
+};
+QML_DECLARE_TYPE(QFxTranslation3D)
+
+class Q_DECLARATIVE_EXPORT QFxPerspective : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle)
+ Q_PROPERTY(qreal aspect READ aspect WRITE setAspect)
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale)
+public:
+ QFxPerspective(QObject *parent=0);
+ ~QFxPerspective();
+
+ qreal angle() const { return _angle; }
+ void setAngle(qreal v) { _angle = v; update(); }
+
+ qreal aspect() const { return _aspect; }
+ void setAspect(qreal v) { _aspect = v; update(); }
+
+ qreal x() const { return _x; }
+ void setX(qreal v) { _x = v; update(); }
+
+ qreal y() const { return _y; }
+ void setY(qreal v) { _y = v; update(); }
+
+ qreal scale() const { return _scale; }
+ void setScale(qreal v) { _scale = v; update(); }
+
+#if defined(QFX_RENDER_OPENGL)
+ virtual bool isIdentity() const;
+ virtual QMatrix4x4 transform() const;
+#endif
+private:
+ qreal _scale;
+ qreal _x;
+ qreal _y;
+ qreal _angle;
+ qreal _aspect;
+};
+QML_DECLARE_TYPE(QFxPerspective)
+
+class Q_DECLARATIVE_EXPORT QFxSquish : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal width READ width WRITE setWidth)
+ Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_PROPERTY(qreal topLeftX READ topLeft_x WRITE settopLeft_x)
+ Q_PROPERTY(qreal topLeftY READ topLeft_y WRITE settopLeft_y)
+ Q_PROPERTY(qreal topRightX READ topRight_x WRITE settopRight_x)
+ Q_PROPERTY(qreal topRightY READ topRight_y WRITE settopRight_y)
+ Q_PROPERTY(qreal bottomLeftX READ bottomLeft_x WRITE setbottomLeft_x)
+ Q_PROPERTY(qreal bottomLeftY READ bottomLeft_y WRITE setbottomLeft_y)
+ Q_PROPERTY(qreal bottomRightX READ bottomRight_x WRITE setbottomRight_x)
+ Q_PROPERTY(qreal bottomRightY READ bottomRight_y WRITE setbottomRight_y)
+public:
+ QFxSquish(QObject *parent=0);
+ ~QFxSquish();
+
+ qreal x() const;
+ void setX(qreal);
+
+ qreal y() const;
+ void setY(qreal);
+
+ qreal width() const;
+ void setWidth(qreal);
+
+ qreal height() const;
+ void setHeight(qreal);
+
+ qreal topLeft_x() const;
+ void settopLeft_x(qreal);
+
+ qreal topLeft_y() const;
+ void settopLeft_y(qreal);
+
+ qreal topRight_x() const;
+ void settopRight_x(qreal);
+
+ qreal topRight_y() const;
+ void settopRight_y(qreal);
+
+ qreal bottomLeft_x() const;
+ void setbottomLeft_x(qreal);
+
+ qreal bottomLeft_y() const;
+ void setbottomLeft_y(qreal);
+
+ qreal bottomRight_y() const;
+ void setbottomRight_y(qreal);
+
+ qreal bottomRight_x() const;
+ void setbottomRight_x(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+private:
+ QPointF p;
+ QSizeF s;
+ QPointF p1, p2, p3, p4;
+};
+QML_DECLARE_TYPE(QFxSquish)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXTRANSFORM_H
diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp
new file mode 100644
index 0000000..c60a379
--- /dev/null
+++ b/src/declarative/fx/qfxvisualitemmodel.cpp
@@ -0,0 +1,771 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlistmodelinterface.h"
+#include "qfxitem.h"
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+#include "qmlpackage.h"
+#include "qhash.h"
+#include "qlist.h"
+#include "private/qobject_p.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include "qmlopenmetaobject.h"
+#include "qmllistaccessor.h"
+#include "qfxvisualitemmodel.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DECLARE_TYPE(QListModelInterface)
+
+class QFxVisualItemModelParts;
+class QFxVisualItemModelData;
+class QFxVisualItemModelPrivate : public QObjectPrivate
+{
+public:
+ QFxVisualItemModelPrivate(QmlContext *);
+
+ QListModelInterface *m_listModelInterface;
+ QAbstractItemModel *m_abstractItemModel;
+ QFxVisualItemModel *m_visualItemModel;
+ QString m_part;
+
+ QmlComponent *m_delegate;
+ QmlContext *m_context;
+ QList<int> m_roles;
+ QHash<int,QString> m_roleNames;
+
+ struct ObjectRef {
+ ObjectRef(QObject *object=0) : obj(object), ref(1) {}
+ QObject *obj;
+ int ref;
+ };
+ class Cache : public QHash<int, ObjectRef> {
+ public:
+ QObject *getItem(int index) {
+ QObject *item = 0;
+ QHash<int,ObjectRef>::iterator it = find(index);
+ if (it != end()) {
+ (*it).ref++;
+ item = (*it).obj;
+ }
+ return item;
+ }
+ QObject *item(int index) {
+ QObject *item = 0;
+ QHash<int, ObjectRef>::const_iterator it = find(index);
+ if (it != end())
+ item = (*it).obj;
+ return item;
+ }
+ void insertItem(int index, QObject *obj) {
+ insert(index, ObjectRef(obj));
+ }
+ bool releaseItem(QObject *obj) {
+ QHash<int, ObjectRef>::iterator it = begin();
+ for (; it != end(); ++it) {
+ ObjectRef &objRef = *it;
+ if (objRef.obj == obj) {
+ if (--objRef.ref == 0) {
+ erase(it);
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+ };
+
+ Cache m_cache;
+ QHash<QObject *, QmlPackage*> m_packaged;
+
+ QFxVisualItemModelParts *m_parts;
+ friend class QFxVisualItemParts;
+
+ QFxVisualItemModelData *data(QObject *item);
+
+ QVariant m_modelVariant;
+ QmlListAccessor *m_modelList;
+
+ int modelCount() const {
+ if (m_visualItemModel)
+ return m_visualItemModel->count();
+ if (m_listModelInterface)
+ return m_listModelInterface->count();
+ if (m_abstractItemModel)
+ return m_abstractItemModel->rowCount();
+ if (m_modelList)
+ return m_modelList->count();
+ return 0;
+ }
+};
+
+class QFxVisualItemModelDataMetaObject : public QmlOpenMetaObject
+{
+public:
+ QFxVisualItemModelDataMetaObject(QObject *parent)
+ : QmlOpenMetaObject(parent) {}
+
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+ virtual int createProperty(const char *, const char *);
+
+private:
+ friend class QFxVisualItemModelData;
+ QList<int> roles;
+};
+
+class QFxVisualItemModelData : public QObject
+{
+Q_OBJECT
+public:
+ QFxVisualItemModelData(int index, QFxVisualItemModelPrivate *model);
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged);
+ int index() const;
+ void setIndex(int index);
+
+ int count() const;
+ int role(int) const;
+ void setValue(int, const QVariant &);
+
+Q_SIGNALS:
+ void indexChanged();
+
+private:
+ friend class QFxVisualItemModelDataMetaObject;
+ int m_index;
+ QFxVisualItemModelPrivate *m_model;
+ QFxVisualItemModelDataMetaObject *m_meta;
+};
+
+int QFxVisualItemModelData::count() const
+{
+ return m_meta->count();
+}
+
+int QFxVisualItemModelData::role(int id) const
+{
+ Q_ASSERT(id >= 0 && id < count());
+ return m_meta->roles.at(id);
+}
+
+void QFxVisualItemModelData::setValue(int id, const QVariant &val)
+{
+ m_meta->setValue(id, val);
+}
+
+int QFxVisualItemModelDataMetaObject::createProperty(const char *name, const char *type)
+{
+ QFxVisualItemModelData *data =
+ static_cast<QFxVisualItemModelData *>(object());
+
+ if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
+ && data->m_model->m_modelList) {
+ if (!qstrcmp(name, "modelData"))
+ return QmlOpenMetaObject::createProperty(name, type);
+ } else {
+ const QLatin1String sname(name);
+ for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
+ iter != data->m_model->m_roleNames.end(); ++iter) {
+
+ if (*iter == sname)
+ return QmlOpenMetaObject::createProperty(name, type);
+ }
+ }
+ return -1;
+}
+
+QVariant
+QFxVisualItemModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+
+ QFxVisualItemModelData *data =
+ static_cast<QFxVisualItemModelData *>(object());
+ QString name = QLatin1String(prop.name());
+ if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
+ && data->m_model->m_modelList) {
+ return data->m_model->m_modelList->at(data->m_index);
+ } else if (data->m_model->m_listModelInterface) {
+ for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
+ iter != data->m_model->m_roleNames.end(); ++iter) {
+
+ if (*iter == name) {
+ roles.append(iter.key());
+ QHash<int,QVariant> values = data->m_model->m_listModelInterface->data(data->m_index, QList<int>() << iter.key());
+ if (values.isEmpty())
+ return QVariant();
+ else
+ return values.value(iter.key());
+ }
+ }
+ } else if (data->m_model->m_abstractItemModel) {
+ for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
+ iter != data->m_model->m_roleNames.end(); ++iter) {
+
+ if (*iter == name) {
+ roles.append(iter.key());
+ QModelIndex index = data->m_model->m_abstractItemModel->index(data->m_index, 0);
+ return data->m_model->m_abstractItemModel->data(index, iter.key());
+ }
+ }
+ }
+ Q_ASSERT(!"Can never be reached");
+ return QVariant();
+}
+
+QFxVisualItemModelData::QFxVisualItemModelData(int index,
+ QFxVisualItemModelPrivate *model)
+: m_index(index), m_model(model),
+ m_meta(new QFxVisualItemModelDataMetaObject(this))
+{
+}
+
+int QFxVisualItemModelData::index() const
+{
+ return m_index;
+}
+
+// This is internal only - it should not be set from qml
+void QFxVisualItemModelData::setIndex(int index)
+{
+ m_index = index;
+ emit indexChanged();
+}
+
+class QFxVisualItemModelPartsMetaObject : public QmlOpenMetaObject
+{
+public:
+ QFxVisualItemModelPartsMetaObject(QObject *parent)
+ : QmlOpenMetaObject(parent) {}
+
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+};
+
+class QFxVisualItemModelParts : public QObject
+{
+Q_OBJECT
+public:
+ QFxVisualItemModelParts(QFxVisualItemModel *parent);
+
+private:
+ friend class QFxVisualItemModelPartsMetaObject;
+ QFxVisualItemModel *model;
+};
+
+QVariant
+QFxVisualItemModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+
+ QFxVisualItemModel *m = new QFxVisualItemModel;
+ m->setParent(object());
+ m->setPart(QLatin1String(prop.name()));
+ m->setModel(QVariant::fromValue(static_cast<QFxVisualItemModelParts *>(object())->model));
+
+ QVariant var = QVariant::fromValue((QObject *)m);
+ return var;
+}
+
+QFxVisualItemModelParts::QFxVisualItemModelParts(QFxVisualItemModel *parent)
+: QObject(parent), model(parent)
+{
+ new QFxVisualItemModelPartsMetaObject(this);
+}
+
+QFxVisualItemModelPrivate::QFxVisualItemModelPrivate(QmlContext *ctxt)
+: m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
+, m_context(ctxt), m_parts(0), m_modelList(0)
+{
+}
+
+QFxVisualItemModelData *QFxVisualItemModelPrivate::data(QObject *item)
+{
+ QList<QFxVisualItemModelData *> dataList =
+ item->findChildren<QFxVisualItemModelData *>();
+ Q_ASSERT(dataList.count() == 1);
+ return dataList.first();
+}
+
+QFxVisualItemModel::QFxVisualItemModel()
+: QObject(*(new QFxVisualItemModelPrivate(0)))
+{
+}
+
+QFxVisualItemModel::QFxVisualItemModel(QmlContext *ctxt)
+: QObject(*(new QFxVisualItemModelPrivate(ctxt)))
+{
+}
+
+QFxVisualItemModel::~QFxVisualItemModel()
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_modelList)
+ delete d->m_modelList;
+}
+
+QVariant QFxVisualItemModel::model() const
+{
+ Q_D(const QFxVisualItemModel);
+ return d->m_modelVariant;
+}
+
+void QFxVisualItemModel::setModel(const QVariant &model)
+{
+ Q_D(QFxVisualItemModel);
+ d->m_modelVariant = model;
+ if (d->m_listModelInterface) {
+ // Assume caller has released all items.
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ d->m_listModelInterface = 0;
+ } else if (d->m_abstractItemModel) {
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ } else if (d->m_visualItemModel) {
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ d->m_visualItemModel = 0;
+ }
+
+ QObject *object = qvariant_cast<QObject *>(model);
+ if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+ if (d->m_listModelInterface) {
+ d->m_roles = d->m_listModelInterface->roles();
+ for (int ii = 0; ii < d->m_roles.count(); ++ii)
+ d->m_roleNames.insert(d->m_roles.at(ii),
+ d->m_listModelInterface->toString(d->m_roles.at(ii)));
+ }
+
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+
+ if (d->m_delegate && d->m_listModelInterface->count())
+ emit itemsInserted(0, d->m_listModelInterface->count());
+ return;
+ } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+ for (QHash<int,QByteArray>::const_iterator it = d->m_abstractItemModel->roleNames().begin();
+ it != d->m_abstractItemModel->roleNames().end(); ++it) {
+ d->m_roles.append(it.key());
+ d->m_roleNames.insert(it.key(), QLatin1String(*it));
+ }
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ return;
+ }
+ if ((d->m_visualItemModel = qvariant_cast<QFxVisualItemModel *>(model))) {
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ return;
+ }
+ if (!d->m_modelList)
+ d->m_modelList = new QmlListAccessor;
+ d->m_modelList->setList(model);
+ if (d->m_delegate && d->modelCount())
+ emit itemsInserted(0, d->modelCount());
+}
+
+QmlComponent *QFxVisualItemModel::delegate() const
+{
+ Q_D(const QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->delegate();
+ return d->m_delegate;
+}
+
+void QFxVisualItemModel::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QFxVisualItemModel);
+ d->m_delegate = delegate;
+ if (d->modelCount())
+ emit itemsInserted(0, d->modelCount());
+}
+
+QString QFxVisualItemModel::part() const
+{
+ Q_D(const QFxVisualItemModel);
+ return d->m_part;
+}
+
+void QFxVisualItemModel::setPart(const QString &part)
+{
+ Q_D(QFxVisualItemModel);
+ d->m_part = part;
+}
+
+int QFxVisualItemModel::count() const
+{
+ Q_D(const QFxVisualItemModel);
+ return d->modelCount();
+}
+
+QFxItem *QFxVisualItemModel::item(int index, bool complete)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, d->m_part.toLatin1(), complete);
+ return item(index, QByteArray(), complete);
+}
+
+/*
+ Returns ReleaseStatus flags.
+*/
+QFxVisualItemModel::ReleaseFlags QFxVisualItemModel::release(QFxItem *item)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->release(item);
+
+ ReleaseFlags stat = 0;
+ QObject *obj = item;
+ bool inPackage = false;
+
+ QHash<QObject*,QmlPackage*>::iterator it = d->m_packaged.find(item);
+ if (it != d->m_packaged.end()) {
+ QmlPackage *package = *it;
+ d->m_packaged.erase(it);
+ if (d->m_packaged.contains(item))
+ stat |= Referenced;
+ inPackage = true;
+ obj = package; // fall through and delete
+ }
+
+ if (d->m_cache.releaseItem(obj)) {
+ if (inPackage)
+ emit destroyingPackage(qobject_cast<QmlPackage*>(obj));
+ stat |= Destroyed;
+ delete obj;
+ } else if (!inPackage) {
+ stat |= Referenced;
+ }
+
+ return stat;
+}
+
+QObject *QFxVisualItemModel::parts()
+{
+ Q_D(QFxVisualItemModel);
+ if (!d->m_parts)
+ d->m_parts = new QFxVisualItemModelParts(this);
+ return d->m_parts;
+}
+
+QFxItem *QFxVisualItemModel::item(int index, const QByteArray &viewId, bool complete)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, viewId, complete);
+
+ if (d->modelCount() <= 0 || !d->m_delegate)
+ return 0;
+
+ QObject *nobj = d->m_cache.getItem(index);
+ if (!nobj) {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QFxVisualItemModelData *data = new QFxVisualItemModelData(index, d);
+ ctxt->setContextProperty(QLatin1String("model"), data);
+ ctxt->addDefaultObject(data);
+ nobj = d->m_delegate->beginCreate(ctxt);
+ if (complete)
+ d->m_delegate->completeCreate();
+ if (nobj) {
+ ctxt->setParent(nobj);
+ data->setParent(nobj);
+ d->m_cache.insertItem(index, nobj);
+ if (QmlPackage *package = qobject_cast<QmlPackage *>(nobj))
+ emit createdPackage(index, package);
+ } else {
+ delete data;
+ delete ctxt;
+ qWarning() << d->m_delegate->errors();
+ }
+ }
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (!item) {
+ QmlPackage *package = qobject_cast<QmlPackage *>(nobj);
+ if (package) {
+ QObject *o = package->part(QLatin1String(viewId));
+ item = qobject_cast<QFxItem *>(o);
+ d->m_packaged.insertMulti(item, package);
+ }
+ }
+
+ return item;
+}
+
+void QFxVisualItemModel::completeItem()
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel) {
+ d->m_visualItemModel->completeItem();
+ return;
+ }
+
+ d->m_delegate->completeCreate();
+}
+
+QVariant QFxVisualItemModel::evaluate(int index, const QString &expression, QObject *objectContext)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->evaluate(index, expression, objectContext);
+
+ if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
+ return QVariant();
+
+ QVariant value;
+ QObject *nobj = d->m_cache.item(index);
+ if (nobj) {
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (item) {
+ QmlExpression e(qmlContext(item), expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ }
+ } else {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QFxVisualItemModelData *data = new QFxVisualItemModelData(index, d);
+ ctxt->addDefaultObject(data);
+ QmlExpression e(ctxt, expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ delete data;
+ delete ctxt;
+ }
+
+ return value;
+}
+
+int QFxVisualItemModel::indexOf(QFxItem *item, QObject *objectContext) const
+{
+ QmlExpression e(qmlContext(item), QLatin1String("index"), objectContext);
+ e.setTrackChange(false);
+ QVariant value = e.value();
+ if (value.isValid())
+ return value.toInt();
+ return -1;
+}
+
+void QFxVisualItemModel::_q_itemsChanged(int index, int count,
+ const QList<int> &roles)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ for (int ii = index; ii < index + count; ++ii) {
+
+ if (QObject *item = d->m_cache.item(ii)) {
+ QFxVisualItemModelData *data = d->data(item);
+
+ for (int prop = 0; prop < data->count(); ++prop) {
+
+ int role = data->role(prop);
+ if (roles.contains(role)) {
+ if (d->m_listModelInterface) {
+ data->setValue(prop, d->m_listModelInterface->data(ii, QList<int>() << role).value(role));
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(ii, 0);
+ data->setValue(prop, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ }
+ }
+
+ }
+}
+
+void QFxVisualItemModel::_q_itemsInserted(int index, int count)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ QHash<int,QFxVisualItemModelPrivate::ObjectRef> items;
+ for (QHash<int,QFxVisualItemModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= index) {
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + count;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QFxVisualItemModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsInserted(index, count);
+}
+
+void QFxVisualItemModel::_q_itemsRemoved(int index, int count)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ QHash<int, QFxVisualItemModelPrivate::ObjectRef> items;
+ for (QHash<int, QFxVisualItemModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ if (iter.key() >= index && iter.key() < index + count) {
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
+ iter = d->m_cache.erase(iter);
+ items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
+ QFxVisualItemModelData *data = d->data(objRef.obj);
+ data->setIndex(-1);
+ } else if (iter.key() >= index + count) {
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - count;
+ iter = d->m_cache.erase(iter);
+ items.insert(index, objRef);
+ QFxVisualItemModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+
+ d->m_cache.unite(items);
+ emit itemsRemoved(index, count);
+}
+
+void QFxVisualItemModel::_q_itemsMoved(int from, int to, int count)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ QHash<int,QFxVisualItemModelPrivate::ObjectRef> items;
+ for (QHash<int,QFxVisualItemModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= from && iter.key() < from + count) {
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - from + to;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QFxVisualItemModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsMoved(from, to, count);
+}
+
+void QFxVisualItemModel::_q_rowsInserted(const QModelIndex &, int begin, int end)
+{
+ _q_itemsInserted(begin, end - begin + 1);
+}
+
+void QFxVisualItemModel::_q_rowsRemoved(const QModelIndex &, int begin, int end)
+{
+ _q_itemsRemoved(begin, end - begin + 1);
+}
+
+void QFxVisualItemModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
+{
+ Q_D(QFxVisualItemModel);
+ _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
+}
+
+void QFxVisualItemModel::_q_createdPackage(int index, QmlPackage *package)
+{
+ Q_D(QFxVisualItemModel);
+ emit createdItem(index, qobject_cast<QFxItem*>(package->part(d->m_part)));
+}
+
+void QFxVisualItemModel::_q_destroyingPackage(QmlPackage *package)
+{
+ Q_D(QFxVisualItemModel);
+ emit destroyingItem(qobject_cast<QFxItem*>(package->part(d->m_part)));
+}
+
+QML_DEFINE_TYPE(QFxVisualItemModel,VisualModel)
+
+QT_END_NAMESPACE
+#include "qfxvisualitemmodel.moc"
diff --git a/src/declarative/fx/qfxvisualitemmodel.h b/src/declarative/fx/qfxvisualitemmodel.h
new file mode 100644
index 0000000..968cc2e
--- /dev/null
+++ b/src/declarative/fx/qfxvisualitemmodel.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXVISUALITEMMODEL_H
+#define QFXVISUALITEMMODEL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractitemmodel.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+/*****************************************************************************
+ *****************************************************************************
+ XXX Experimental
+ *****************************************************************************
+*****************************************************************************/
+
+class QFxItem;
+class QmlComponent;
+class QmlPackage;
+class QFxVisualItemModelPrivate;
+class Q_DECLARATIVE_EXPORT QFxVisualItemModel : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFxVisualItemModel)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(QString part READ part WRITE setPart)
+ Q_PROPERTY(QObject *parts READ parts)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+public:
+ QFxVisualItemModel();
+ QFxVisualItemModel(QmlContext *);
+ virtual ~QFxVisualItemModel();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ QString part() const;
+ void setPart(const QString &);
+
+ enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
+ Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
+
+ int count() const;
+ QFxItem *item(int index, bool complete=true);
+ QFxItem *item(int index, const QByteArray &, bool complete=true);
+ ReleaseFlags release(QFxItem *item);
+ void completeItem();
+ QVariant evaluate(int index, const QString &expression, QObject *objectContext);
+
+ int indexOf(QFxItem *item, QObject *objectContext) const;
+
+ QObject *parts();
+
+Q_SIGNALS:
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void createdItem(int index, QFxItem *item);
+ void createdPackage(int index, QmlPackage *package);
+ void destroyingItem(QFxItem *item);
+ void destroyingPackage(QmlPackage *package);
+
+private Q_SLOTS:
+ void _q_itemsChanged(int, int, const QList<int> &);
+ void _q_itemsInserted(int index, int count);
+ void _q_itemsRemoved(int index, int count);
+ void _q_itemsMoved(int from, int to, int count);
+ void _q_rowsInserted(const QModelIndex &,int,int);
+ void _q_rowsRemoved(const QModelIndex &,int,int);
+ void _q_dataChanged(const QModelIndex&,const QModelIndex&);
+ void _q_createdPackage(int index, QmlPackage *package);
+ void _q_destroyingPackage(QmlPackage *package);
+
+private:
+ Q_DISABLE_COPY(QFxVisualItemModel)
+};
+QML_DECLARE_TYPE(QFxVisualItemModel)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXVISUALITEMMODEL_H
diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp
new file mode 100644
index 0000000..bfccd34
--- /dev/null
+++ b/src/declarative/fx/qfxwebview.cpp
@@ -0,0 +1,1076 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QBasicTimer>
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtWebKit/QWebPage>
+#include <QtWebKit/QWebFrame>
+
+#include "qml.h"
+#include "qmlbindablevalue.h"
+#include "qmlengine.h"
+#include "qmlstate.h"
+#include "qfxtransform.h"
+#include "qfxscalegrid.h"
+#include "qsimplecanvas.h"
+#include "qlistmodelinterface.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glsave.h>
+#endif
+#if defined(QFX_RENDER_OPENGL)
+#include <gltexture.h>
+#endif
+
+#include "qfxwebview.h"
+#include <qsimplecanvasfilter.h>
+#include <private/qfxpainteditem_p.h>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxWebView,WebView)
+
+static const int MAX_DOUBLECLICK_TIME=500; // XXX need better gesture system
+
+class QFxWebSettings : public QObject {
+ Q_OBJECT
+ /*
+ StandardFont,
+ FixedFont,
+ SerifFont,
+ SansSerifFont,
+ CursiveFont,
+ FantasyFont
+
+ MinimumFontSize,
+ MinimumLogicalFontSize,
+ DefaultFontSize,
+ DefaultFixedFontSize
+ */
+
+ Q_PROPERTY(bool autoLoadImages READ autoLoadImages WRITE setAutoLoadImages)
+ Q_PROPERTY(bool javascriptEnabled READ javascriptEnabled WRITE setJavascriptEnabled)
+ Q_PROPERTY(bool javaEnabled READ javaEnabled WRITE setJavaEnabled)
+ Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled)
+ Q_PROPERTY(bool privateBrowsingEnabled READ privateBrowsingEnabled WRITE setPrivateBrowsingEnabled)
+ Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows)
+ Q_PROPERTY(bool javascriptCanAccessClipboard READ javascriptCanAccessClipboard WRITE setJavascriptCanAccessClipboard)
+ Q_PROPERTY(bool developerExtrasEnabled READ developerExtrasEnabled WRITE setDeveloperExtrasEnabled)
+ Q_PROPERTY(bool linksIncludedInFocusChain READ linksIncludedInFocusChain WRITE setLinksIncludedInFocusChain)
+ Q_PROPERTY(bool zoomTextOnly READ zoomTextOnly WRITE setZoomTextOnly)
+ Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds)
+ Q_PROPERTY(bool offlineStorageDatabaseEnabled READ offlineStorageDatabaseEnabled WRITE setOfflineStorageDatabaseEnabled)
+ Q_PROPERTY(bool offlineWebApplicationCacheEnabled READ offlineWebApplicationCacheEnabled WRITE setOfflineWebApplicationCacheEnabled)
+ Q_PROPERTY(bool localStorageDatabaseEnabled READ localStorageDatabaseEnabled WRITE setLocalStorageDatabaseEnabled)
+
+public:
+ QFxWebSettings() {}
+
+ bool autoLoadImages() const { return s->testAttribute(QWebSettings::AutoLoadImages); }
+ void setAutoLoadImages(bool on) { s->setAttribute(QWebSettings::AutoLoadImages, on); }
+ bool javascriptEnabled() const { return s->testAttribute(QWebSettings::JavascriptEnabled); }
+ void setJavascriptEnabled(bool on) { s->setAttribute(QWebSettings::JavascriptEnabled, on); }
+ bool javaEnabled() const { return s->testAttribute(QWebSettings::JavaEnabled); }
+ void setJavaEnabled(bool on) { s->setAttribute(QWebSettings::JavaEnabled, on); }
+ bool pluginsEnabled() const { return s->testAttribute(QWebSettings::PluginsEnabled); }
+ void setPluginsEnabled(bool on) { s->setAttribute(QWebSettings::PluginsEnabled, on); }
+ bool privateBrowsingEnabled() const { return s->testAttribute(QWebSettings::PrivateBrowsingEnabled); }
+ void setPrivateBrowsingEnabled(bool on) { s->setAttribute(QWebSettings::PrivateBrowsingEnabled, on); }
+ bool javascriptCanOpenWindows() const { return s->testAttribute(QWebSettings::JavascriptCanOpenWindows); }
+ void setJavascriptCanOpenWindows(bool on) { s->setAttribute(QWebSettings::JavascriptCanOpenWindows, on); }
+ bool javascriptCanAccessClipboard() const { return s->testAttribute(QWebSettings::JavascriptCanAccessClipboard); }
+ void setJavascriptCanAccessClipboard(bool on) { s->setAttribute(QWebSettings::JavascriptCanAccessClipboard, on); }
+ bool developerExtrasEnabled() const { return s->testAttribute(QWebSettings::DeveloperExtrasEnabled); }
+ void setDeveloperExtrasEnabled(bool on) { s->setAttribute(QWebSettings::DeveloperExtrasEnabled, on); }
+ bool linksIncludedInFocusChain() const { return s->testAttribute(QWebSettings::LinksIncludedInFocusChain); }
+ void setLinksIncludedInFocusChain(bool on) { s->setAttribute(QWebSettings::LinksIncludedInFocusChain, on); }
+ bool zoomTextOnly() const { return s->testAttribute(QWebSettings::ZoomTextOnly); }
+ void setZoomTextOnly(bool on) { s->setAttribute(QWebSettings::ZoomTextOnly, on); }
+ bool printElementBackgrounds() const { return s->testAttribute(QWebSettings::PrintElementBackgrounds); }
+ void setPrintElementBackgrounds(bool on) { s->setAttribute(QWebSettings::PrintElementBackgrounds, on); }
+ bool offlineStorageDatabaseEnabled() const { return s->testAttribute(QWebSettings::OfflineStorageDatabaseEnabled); }
+ void setOfflineStorageDatabaseEnabled(bool on) { s->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, on); }
+ bool offlineWebApplicationCacheEnabled() const { return s->testAttribute(QWebSettings::OfflineWebApplicationCacheEnabled); }
+ void setOfflineWebApplicationCacheEnabled(bool on) { s->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, on); }
+ bool localStorageDatabaseEnabled() const { return s->testAttribute(QWebSettings::LocalStorageDatabaseEnabled); }
+ void setLocalStorageDatabaseEnabled(bool on) { s->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, on); }
+
+ QWebSettings *s;
+};
+
+
+class QFxWebViewPrivate : public QFxPaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxWebView)
+
+public:
+ QFxWebViewPrivate()
+ : QFxPaintedItemPrivate(), page(0), idealwidth(0), idealheight(0), interactive(true), lastPress(0), lastRelease(0), mouseX(0), mouseY(0),
+ max_imagecache_size(100000), progress(1.0), pending(PendingNone)
+ {
+ }
+
+ QWebPage *page;
+
+ struct ImageCacheItem {
+ ImageCacheItem() : age(0) {}
+ ~ImageCacheItem() { }
+ int age;
+ QRect area;
+#if defined(QFX_RENDER_QPAINTER)
+ QPixmap image;
+#else
+ GLTexture image;
+#endif
+ };
+ QList<ImageCacheItem*> imagecache;
+ void dirtyCache(const QRect& dirt)
+ {
+ for (int i=0; i<imagecache.count(); ) {
+ if (imagecache[i]->area.intersects(dirt)) {
+ imagecache.removeAt(i);
+ } else {
+ ++i;
+ }
+ }
+ }
+ void clearCache()
+ {
+ foreach (ImageCacheItem* i, imagecache)
+ delete i;
+ imagecache.clear();
+ }
+
+ int idealwidth;
+ int idealheight;
+ bool interactive;
+ QMouseEvent *lastPress, *lastRelease;
+ int mouseX, mouseY;
+ int max_imagecache_size;
+ qreal progress;
+ QBasicTimer dcTimer;
+ QString statusBarMessage;
+ enum { PendingNone, PendingUrl, PendingHtml, PendingContent } pending;
+ QUrl pending_url;
+ QString pending_string;
+ QByteArray pending_data;
+ mutable QFxWebSettings settings;
+};
+
+
+/*!
+ \qmlclass WebView
+ \brief The WebView item allows you to add web content to a canvas.
+ \inherits Item
+
+ A WebView renders web content based on a URL.
+
+ If the width and height of the item is not set, they will
+ dynamically adjust to a size appropriate for the content.
+ This width may be large (eg. 980) for typical online web pages.
+
+ If the idealWidth is set, the width will be this amount or larger,
+ usually laying out the web content to fit the idealWidth.
+
+ If the idealHeight is set, the height will be this amount or larger.
+ Due to WebKit limitations, the height may be more than necessary
+ if the idealHeight is changed after the content is loaded.
+
+ \qml
+ WebView {
+ url: "http://www.nokia.com"
+ width: 490
+ height: 400
+ scale: 0.5
+ smooth: true
+ }
+ \endqml
+
+ \image webview.png
+
+ The item includes no scrolling, scaling,
+ toolbars, etc., those must be implemented around WebView. See the WebBrowser example
+ for a demonstration of this.
+*/
+
+/*!
+ \internal
+ \class QFxWebView
+ \brief The QFxWebView class allows you to add web content to a QFxView.
+
+ A WebView renders web content base on a URL.
+
+ \image webview.png
+
+ The item includes no scrolling, scaling,
+ toolbars, etc., those must be implemented around WebView. See the WebBrowser example
+ for a demonstration of this.
+
+ A QFxWebView object can be instantiated in Qml using the tag \l WebView.
+*/
+
+QFxWebView::QFxWebView(QFxItem *parent)
+ : QFxPaintedItem(*(new QFxWebViewPrivate), parent)
+{
+ init();
+}
+
+QFxWebView::QFxWebView(QFxWebViewPrivate &dd, QFxItem *parent)
+ : QFxPaintedItem(dd, parent)
+{
+ init();
+}
+
+QFxWebView::~QFxWebView()
+{
+ Q_D(QFxWebView);
+ delete d->page;
+}
+
+void QFxWebView::init()
+{
+ Q_D(QFxWebView);
+
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setOptions(HasContents | MouseEvents);
+ setFocusable(true);
+
+ d->page = 0;
+}
+
+void QFxWebView::componentComplete()
+{
+ QFxPaintedItem::componentComplete();
+ Q_D(QFxWebView);
+ switch (d->pending) {
+ case QFxWebViewPrivate::PendingUrl:
+ setUrl(d->pending_url.toString());
+ break;
+ case QFxWebViewPrivate::PendingHtml:
+ setHtml(d->pending_string, d->pending_url);
+ break;
+ case QFxWebViewPrivate::PendingContent:
+ setContent(d->pending_data, d->pending_string, d->pending_url);
+ break;
+ default:
+ break;
+ }
+ d->pending = QFxWebViewPrivate::PendingNone;
+}
+
+/*!
+ \qmlproperty real WebView::progress
+ This property holds the progress of loading the current URL, from 0 to 1.
+*/
+/*!
+ \property QFxWebView::progress
+ \brief the progress of loading the current URL, from 0 to 1.
+*/
+qreal QFxWebView::progress() const
+{
+ Q_D(const QFxWebView);
+ return d->progress;
+}
+
+void QFxWebView::doLoadProgress(int p)
+{
+ Q_D(QFxWebView);
+ if (d->progress == p/100.0)
+ return;
+ d->progress = p/100.0;
+ expandToWebPage();
+ emit progressChanged();
+}
+
+void QFxWebView::doLoadFinished(bool ok)
+{
+ // XXX bug 232556 - pages with no title never get this signal
+ if (title().isEmpty())
+ emit urlChanged();
+
+ if (ok) {
+ emit loadFinished();
+ } else {
+ emit loadFailed();
+ }
+}
+
+/*!
+ \qmlproperty string WebView::url
+ This property holds the URL to the page displayed in this item.
+
+ Note that after this property is set, it may take some time
+ before the change is notified, as this only happens when
+ loading of the URL successfully starts.
+*/
+/*!
+ \property QFxWebView::url
+ \brief the URL to the page displayed in this item.
+
+ \sa urlChanged()
+*/
+/*!
+ \fn void QFxWebView::urlChanged()
+
+ Emitted when loading of the URL successfully starts after
+ setUrl() is called.
+*/
+QString QFxWebView::url() const
+{
+ return page()->mainFrame()->url().toString();
+}
+
+void QFxWebView::setUrl(const QString &n)
+{
+ Q_D(QFxWebView);
+ if (n == page()->mainFrame()->url().toString())
+ return;
+
+ page()->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : width(),
+ d->idealheight>0 ? d->idealheight : height()));
+
+ QUrl url(n);
+ if (url.isRelative())
+ url = qmlContext(this)->resolvedUrl(n);
+
+ if (isComponentComplete())
+ page()->mainFrame()->load(url);
+ else {
+ d->pending = d->PendingUrl;
+ d->pending_url = url;
+ }
+
+ // emit urlChanged() - not until actually loaded
+}
+
+/*!
+ \qmlproperty int WebView::idealWidth
+ This property holds the ideal width for displaying the current URL.
+*/
+/*!
+ \property QFxWebView::idealWidth
+ \brief the ideal width for displaying the current URL.
+*/
+int QFxWebView::idealWidth() const
+{
+ Q_D(const QFxWebView);
+ return d->idealwidth;
+}
+
+void QFxWebView::setIdealWidth(int iw)
+{
+ Q_D(QFxWebView);
+ if (d->idealwidth == iw) return;
+ d->idealwidth = iw;
+ expandToWebPage();
+ emit idealWidthChanged();
+}
+
+/*!
+ \qmlproperty int WebView::idealHeight
+ This property holds the ideal height for displaying the current URL.
+*/
+/*!
+ \property QFxWebView::idealHeight
+ \brief the ideal height for displaying the current URL.
+*/
+int QFxWebView::idealHeight() const
+{
+ Q_D(const QFxWebView);
+ return d->idealheight;
+}
+
+void QFxWebView::setIdealHeight(int ih)
+{
+ Q_D(QFxWebView);
+ if (d->idealheight == ih) return;
+ d->idealheight = ih;
+ expandToWebPage();
+ emit idealHeightChanged();
+}
+
+/*!
+ \qmlproperty bool WebView::interactive
+
+ This property holds controls whether the item responds to mouse and
+ key events.
+*/
+
+/*!
+ \property QFxWebView::interactive
+
+ \brief controls whether the item responds to mouse and key events.
+*/
+bool QFxWebView::interactive() const
+{
+ Q_D(const QFxWebView);
+ return d->interactive;
+}
+
+void QFxWebView::setInteractive(bool i)
+{
+ Q_D(QFxWebView);
+ if (d->interactive == i) return;
+ d->interactive = i;
+ emit interactiveChanged();
+}
+
+void QFxWebView::updateCacheForVisibility()
+{
+ Q_D(QFxWebView);
+ if (!isVisible())
+ d->clearCache();
+}
+
+void QFxWebView::expandToWebPage()
+{
+ Q_D(QFxWebView);
+ QSize cs = page()->mainFrame()->contentsSize();
+ if (cs.width() < d->idealwidth)
+ cs.setWidth(d->idealwidth);
+ if (cs.height() < d->idealheight)
+ cs.setHeight(d->idealheight);
+ if (widthValid() && cs.width() < width())
+ cs.setWidth(width());
+ if (heightValid() && cs.height() < height())
+ cs.setHeight(height());
+ if (cs != page()->viewportSize()) {
+ page()->setViewportSize(cs);
+ d->clearCache();
+ setImplicitWidth(cs.width());
+ setImplicitHeight(cs.height());
+ }
+}
+
+void QFxWebView::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.size() != oldGeometry.size())
+ expandToWebPage();
+ QFxPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void QFxWebView::paintPage(const QRect& r)
+{
+ Q_D(QFxWebView);
+ if (d->page->mainFrame()->contentsSize() != contentsSize())
+ setContentsSize(d->page->mainFrame()->contentsSize());
+ dirtyCache(r);
+ update();
+}
+
+/*!
+ \qmlproperty int WebView::cacheSize
+
+ This property holds the maximum number of pixels of image cache to
+ allow. The default is 0.1 megapixels. The cache will not be larger
+ than the (unscaled) size of the WebView.
+*/
+
+/*!
+ \property QFxWebView::cacheSize
+
+ The maximum number of pixels of image cache to allow. The default
+ is 0.1 megapixels. The cache will not be larger than the (unscaled)
+ size of the QFxWebView.
+*/
+int QFxWebView::cacheSize() const
+{
+ Q_D(const QFxWebView);
+ return d->max_imagecache_size;
+}
+
+void QFxWebView::setCacheSize(int pixels)
+{
+ Q_D(QFxWebView);
+ if (pixels < d->max_imagecache_size) {
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ cachesize += area.width()*area.height();
+ }
+ while (d->imagecache.count() && cachesize > pixels) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ d->imagecache.removeAt(oldest);
+ }
+ }
+ d->max_imagecache_size = pixels;
+}
+
+void QFxWebView::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "url:" << url();
+ QFxPaintedItem::dump(depth);
+}
+
+void QFxWebView::drawContents(QPainter *p, const QRect &r)
+{
+ page()->mainFrame()->render(p,r);
+}
+
+QString QFxWebView::propertyInfo() const
+{
+ return page()->mainFrame()->url().toString();
+}
+
+static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e)
+{
+ QEvent::Type t;
+ switch(e->type()) {
+ default:
+ case QEvent::GraphicsSceneMousePress:
+ t = QEvent::MouseButtonPress;
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ t = QEvent::MouseButtonRelease;
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ t = QEvent::MouseMove;
+ break;
+ case QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick:
+ t = QEvent::MouseButtonDblClick;
+ break;
+ }
+
+ QMouseEvent *me = new QMouseEvent(t, e->pos().toPoint(), e->button(), e->buttons(), 0);
+ return me;
+}
+
+
+void QFxWebView::timerEvent(QTimerEvent *event)
+{
+ Q_D(QFxWebView);
+ if (event->timerId() ==d->dcTimer.timerId()) {
+ d->dcTimer.stop();
+ if (d->lastPress) {
+ page()->event(d->lastPress);
+ delete d->lastPress;
+ d->lastPress = 0;
+ }
+ if (d->lastRelease) {
+ page()->event(d->lastRelease);
+ delete d->lastRelease;
+ d->lastRelease = 0;
+ }
+ }
+}
+
+int QFxWebView::mouseX() const
+{
+ Q_D(const QFxWebView);
+ if (d->lastPress)
+ return d->lastPress->x();
+ if (d->lastRelease)
+ return d->lastRelease->x();
+ return d->mouseX;
+}
+
+int QFxWebView::mouseY() const
+{
+ Q_D(const QFxWebView);
+ if (d->lastPress)
+ return d->lastPress->y();
+ if (d->lastRelease)
+ return d->lastRelease->y();
+ return d->mouseY;
+}
+
+void QFxWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ Q_D(QFxWebView);
+ d->dcTimer.stop();
+ delete d->lastPress;
+ delete d->lastRelease;
+ d->lastPress = 0;
+ d->lastRelease = 0;
+ d->mouseX = me->x();
+ d->mouseY = me->y();
+ emit doubleClick();
+ d->mouseX = 0;
+ d->mouseY = 0;
+ delete me;
+}
+
+void QFxWebView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxWebView);
+ if (d->interactive) {
+ d->lastPress = sceneMouseEventToMouseEvent(event);
+ event->setAccepted(true);
+ } else {
+ event->setAccepted(false);
+ }
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+void QFxWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxWebView);
+ if (d->interactive) {
+ d->lastRelease = sceneMouseEventToMouseEvent(event);
+ d->dcTimer.start(MAX_DOUBLECLICK_TIME,this);
+ event->setAccepted(true);
+ } else {
+ event->setAccepted(false);
+ }
+ if (!event->isAccepted())
+ QFxPaintedItem::mouseReleaseEvent(event);
+}
+
+void QFxWebView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(const QFxWebView);
+ if (d->interactive && !d->dcTimer.isActive()) {
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ page()->event(me);
+ event->setAccepted(
+#if QT_VERSION <= 0x040500 // XXX see bug 230835
+ true
+#else
+ me->isAccepted()
+#endif
+ );
+ delete me;
+ } else {
+ event->setAccepted(false);
+ }
+ if (!event->isAccepted())
+ QFxPaintedItem::mouseMoveEvent(event);
+}
+
+void QFxWebView::keyPressEvent(QKeyEvent* event)
+{
+ Q_D(const QFxWebView);
+ if (d->interactive)
+ page()->event(event);
+ if (!event->isAccepted())
+ QFxPaintedItem::keyPressEvent(event);
+}
+
+void QFxWebView::keyReleaseEvent(QKeyEvent* event)
+{
+ Q_D(const QFxWebView);
+ if (d->interactive)
+ page()->event(event);
+ if (!event->isAccepted())
+ QFxPaintedItem::keyReleaseEvent(event);
+}
+
+/*!
+ \qmlproperty action WebView::back
+ This property holds the action for causing the previous URL in the history to be displayed.
+*/
+QAction *QFxWebView::backAction() const
+{
+ return page()->action(QWebPage::Back);
+}
+
+/*!
+ \qmlproperty action WebView::forward
+ This property holds the action for causing the next URL in the history to be displayed.
+*/
+QAction *QFxWebView::forwardAction() const
+{
+ return page()->action(QWebPage::Forward);
+}
+
+/*!
+ \qmlproperty action WebView::reload
+ This property holds the action for reloading with the current URL
+*/
+QAction *QFxWebView::reloadAction() const
+{
+ return page()->action(QWebPage::Reload);
+}
+
+/*!
+ \qmlproperty action WebView::stop
+ This property holds the action for stopping loading with the current URL
+*/
+QAction *QFxWebView::stopAction() const
+{
+ return page()->action(QWebPage::Stop);
+}
+
+/*!
+ \qmlproperty real WebView::title
+ This property holds the title of the web page currently viewed
+
+ By default, this property contains an empty string.
+*/
+/*!
+ \property QFxWebView::title
+ This property holds the title of the web page currently viewed
+
+ By default, this property contains an empty string.
+
+ \sa titleChanged()
+*/
+QString QFxWebView::title() const
+{
+ return page()->mainFrame()->title();
+}
+
+
+
+/*!
+ \qmlproperty pixmap WebView::icon
+ This property holds the icon associated with the web page currently viewed
+*/
+/*!
+ \property QFxWebView::icon
+ \brief the icon associated with the web page currently viewed
+
+ By default, this property contains a null icon.
+
+ \sa iconChanged(), QWebSettings::iconForUrl()
+*/
+QPixmap QFxWebView::icon() const
+{
+ return page()->mainFrame()->icon().pixmap(QSize(256,256));
+}
+
+
+/*!
+ \qmlproperty real WebView::textSizeMultiplier
+ This property holds multiplier used to scale the text in a Web page
+*/
+/*!
+ Sets the value of the multiplier used to scale the text in a Web page to
+ the \a factor specified.
+*/
+void QFxWebView::setTextSizeMultiplier(qreal factor)
+{
+ page()->mainFrame()->setTextSizeMultiplier(factor);
+}
+
+/*!
+ Returns the value of the multiplier used to scale the text in a Web page.
+*/
+qreal QFxWebView::textSizeMultiplier() const
+{
+ return page()->mainFrame()->textSizeMultiplier();
+}
+
+void QFxWebView::setStatusBarMessage(const QString& s)
+{
+ Q_D(QFxWebView);
+ d->statusBarMessage = s;
+ emit statusChanged();
+}
+
+QString QFxWebView::status() const
+{
+ Q_D(const QFxWebView);
+ return d->statusBarMessage;
+}
+
+QWebPage *QFxWebView::page() const
+{
+ Q_D(const QFxWebView);
+
+ if (!d->page) {
+ QFxWebView *self = const_cast<QFxWebView*>(this);
+ QWebPage *wp = new QFxWebPage(self);
+
+ // QML items don't default to having a background,
+ // even though most we pages will set one anyway.
+ QPalette pal = QApplication::palette();
+ pal.setBrush(QPalette::Base, QColor::fromRgbF(0, 0, 0, 0));
+ wp->setPalette(pal);
+
+ wp->setNetworkAccessManager(qmlEngine(this)->networkAccessManager());
+
+ self->setPage(wp);
+
+ return wp;
+ }
+
+ return d->page;
+}
+
+
+// The QObject interface to settings().
+/*!
+ \qmlproperty bool WebView::settings.autoLoadImages
+ \qmlproperty bool WebView::settings.javascriptEnabled
+ \qmlproperty bool WebView::settings.javaEnabled
+ \qmlproperty bool WebView::settings.pluginsEnabled
+ \qmlproperty bool WebView::settings.privateBrowsingEnabled
+ \qmlproperty bool WebView::settings.javascriptCanOpenWindows
+ \qmlproperty bool WebView::settings.javascriptCanAccessClipboard
+ \qmlproperty bool WebView::settings.developerExtrasEnabled
+ \qmlproperty bool WebView::settings.linksIncludedInFocusChain
+ \qmlproperty bool WebView::settings.zoomTextOnly
+ \qmlproperty bool WebView::settings.printElementBackgrounds
+ \qmlproperty bool WebView::settings.offlineStorageDatabaseEnabled
+ \qmlproperty bool WebView::settings.offlineWebApplicationCacheEnabled
+ \qmlproperty bool WebView::settings.localStorageDatabaseEnabled
+
+ These properties give access to the settings controlling the web view.
+
+ See QWebSettings for the list of sub-properties.
+
+ \qml
+ WebView {
+ settings.pluginsEnabled: true
+ ...
+ }
+ \endqml
+*/
+QObject *QFxWebView::settingsObject() const
+{
+ Q_D(const QFxWebView);
+ d->settings.s = page()->settings();
+ return &d->settings;
+}
+
+void QFxWebView::setPage(QWebPage *page)
+{
+ Q_D(QFxWebView);
+ if (d->page == page)
+ return;
+ if (d->page) {
+ if (d->page->parent() == this) {
+ delete d->page;
+ } else {
+ d->page->disconnect(this);
+ }
+ }
+ d->page = page;
+ d->page->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : -1,
+ d->idealheight>0 ? d->idealheight : -1));
+ d->page->mainFrame()->setScrollBarPolicy(Qt::Horizontal,Qt::ScrollBarAlwaysOff);
+ d->page->mainFrame()->setScrollBarPolicy(Qt::Vertical,Qt::ScrollBarAlwaysOff);
+ connect(this,SIGNAL(visibleChanged()),this,SLOT(updateCacheForVisibility()));
+ connect(d->page,SIGNAL(repaintRequested(QRect)),this,SLOT(paintPage(QRect)));
+ connect(d->page->mainFrame(),SIGNAL(urlChanged(QUrl)),this,SIGNAL(urlChanged()));
+ connect(d->page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
+ connect(d->page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged()));
+
+ connect(d->page,SIGNAL(loadStarted()),this,SIGNAL(loadStarted()));
+ connect(d->page,SIGNAL(loadProgress(int)),this,SLOT(doLoadProgress(int)));
+ connect(d->page,SIGNAL(loadFinished(bool)),this,SLOT(doLoadFinished(bool)));
+ connect(d->page,SIGNAL(statusBarMessage(QString)),this,SLOT(setStatusBarMessage(QString)));
+}
+
+void QFxWebView::load(const QNetworkRequest &request,
+ QNetworkAccessManager::Operation operation,
+ const QByteArray &body)
+{
+ page()->mainFrame()->load(request, operation, body);
+}
+
+QString QFxWebView::html() const
+{
+ return page()->mainFrame()->toHtml();
+}
+
+/*!
+ \qmlproperty string WebView::html
+ This property holds HTML text set directly
+
+ The html property can be set as a string.
+
+ \qml
+ WebView {
+ html: "<p>This is <b>HTML</b>."
+ }
+ \endqml
+*/
+void QFxWebView::setHtml(const QString &html, const QUrl &baseUrl)
+{
+ Q_D(QFxWebView);
+ page()->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : width(),
+ d->idealheight>0 ? d->idealheight : height()));
+ if (isComponentComplete())
+ page()->mainFrame()->setHtml(html, qmlContext(this)->resolvedUrl(baseUrl));
+ else {
+ d->pending = d->PendingHtml;
+ d->pending_url = baseUrl;
+ d->pending_string = html;
+ }
+}
+
+void QFxWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
+{
+ Q_D(QFxWebView);
+ page()->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : width(),
+ d->idealheight>0 ? d->idealheight : height()));
+
+ if (isComponentComplete())
+ page()->mainFrame()->setContent(data,mimeType,qmlContext(this)->resolvedUrl(baseUrl));
+ else {
+ d->pending = d->PendingContent;
+ d->pending_url = baseUrl;
+ d->pending_string = mimeType;
+ d->pending_data = data;
+ }
+}
+
+QWebHistory *QFxWebView::history() const
+{
+ return page()->history();
+}
+
+QWebSettings *QFxWebView::settings() const
+{
+ return page()->settings();
+}
+
+/*!
+ \internal
+ \class QFxWebPage
+ \brief The QFxWebPage class is a QWebPage that can create QML plugins.
+
+ \sa QFxWebView
+*/
+QFxWebPage::QFxWebPage(QFxWebView *parent) :
+ QWebPage(parent)
+{
+}
+
+QFxWebPage::~QFxWebPage()
+{
+}
+
+/*
+ Qt WebKit does not understand non-QWidget plugins, so dummy widgets
+ are created, parented to a single dummy tool window.
+
+ The requirements for QML object plugins are input to the Qt WebKit
+ non-QWidget plugin support, which will obsolete this kludge.
+*/
+class QWidget_Dummy_Plugin : public QWidget
+{
+ Q_OBJECT
+public:
+ static QWidget *dummy_shared_parent()
+ {
+ static QWidget *dsp = 0;
+ if (!dsp) {
+ dsp = new QWidget(0,Qt::Tool);
+ dsp->setGeometry(-10000,-10000,0,0);
+ dsp->show();
+ }
+ return dsp;
+ }
+ QWidget_Dummy_Plugin(const QUrl& url, QFxWebView *view, const QStringList &paramNames, const QStringList &paramValues) :
+ QWidget(dummy_shared_parent()),
+ propertyNames(paramNames),
+ propertyValues(paramValues),
+ webview(view)
+ {
+ QmlEngine *engine = qmlEngine(webview);
+ component = new QmlComponent(engine, url, this);
+ item = 0;
+ if (component->isReady())
+ qmlLoaded();
+ else
+ connect(component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(qmlLoaded()));
+ }
+
+public Q_SLOTS:
+ void qmlLoaded()
+ {
+ item = qobject_cast<QFxItem*>(component->create(qmlContext(webview)));
+ item->setParent(webview);
+ for (int i=0; i<propertyNames.count(); ++i) {
+ if (propertyNames[i] != QLatin1String("type") && propertyNames[i] != QLatin1String("data")) {
+ item->setProperty(propertyNames[i].toLatin1(),propertyValues[i]);
+ }
+ }
+ resizeEvent(0);
+ delete component;
+ component = 0;
+ }
+ void resizeEvent(QResizeEvent*)
+ {
+ if (item) {
+ item->setX(x());
+ item->setY(y());
+ item->setWidth(width());
+ item->setHeight(height());
+ }
+ }
+
+private:
+ QmlComponent *component;
+ QFxItem *item;
+ QStringList propertyNames, propertyValues;
+ QFxWebView *webview;
+};
+
+QFxWebView *QFxWebPage::view()
+{
+ return static_cast<QFxWebView*>(parent());
+}
+
+QObject *QFxWebPage::createPlugin(const QString &, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
+{
+ QUrl comp = qmlContext(view())->resolvedUri(url.toString());
+ return new QWidget_Dummy_Plugin(comp,view(),paramNames,paramValues);
+}
+
+#include "qfxwebview.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h
new file mode 100644
index 0000000..28ef6c3
--- /dev/null
+++ b/src/declarative/fx/qfxwebview.h
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXWEBVIEW_H
+#define QFXWEBVIEW_H
+
+#include <QtGui/QAction>
+#include <QtCore/QUrl>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qfxpainteditem.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtWebKit/QWebPage>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QWebHistory;
+class QWebSettings;
+class QFxWebViewPrivate;
+class QNetworkRequest;
+class QFxWebView;
+
+class Q_DECLARATIVE_EXPORT QFxWebPage : public QWebPage
+{
+ Q_OBJECT
+public:
+ explicit QFxWebPage(QFxWebView *parent);
+ ~QFxWebPage();
+protected:
+ QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues);
+private:
+ QFxWebView *view();
+};
+
+
+class Q_DECLARATIVE_EXPORT QFxWebView : public QFxPaintedItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString title READ title NOTIFY titleChanged)
+ Q_PROPERTY(QPixmap icon READ icon NOTIFY iconChanged)
+ Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false)
+ Q_PROPERTY(QString status READ status NOTIFY statusChanged)
+
+ Q_PROPERTY(int mouseX READ mouseX)
+ Q_PROPERTY(int mouseY READ mouseY)
+
+ Q_PROPERTY(QString html READ html WRITE setHtml)
+
+ Q_PROPERTY(int idealWidth READ idealWidth WRITE setIdealWidth NOTIFY idealWidthChanged)
+ Q_PROPERTY(int idealHeight READ idealHeight WRITE setIdealHeight NOTIFY idealHeightChanged)
+ Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+
+ Q_PROPERTY(bool interactive READ interactive WRITE setInteractive NOTIFY interactiveChanged)
+
+ Q_PROPERTY(int cacheSize READ cacheSize WRITE setCacheSize)
+
+ Q_PROPERTY(QObject* reload READ reloadAction)
+ Q_PROPERTY(QObject* back READ backAction)
+ Q_PROPERTY(QObject* forward READ forwardAction)
+ Q_PROPERTY(QObject* stop READ stopAction)
+
+ Q_PROPERTY(QObject* settings READ settingsObject)
+
+public:
+ QFxWebView(QFxItem *parent=0);
+ ~QFxWebView();
+
+ QString url() const;
+ void setUrl(const QString &);
+
+ QString title() const;
+
+ QPixmap icon() const;
+
+ qreal textSizeMultiplier() const;
+ void setTextSizeMultiplier(qreal);
+
+ bool interactive() const;
+ void setInteractive(bool);
+
+ int cacheSize() const;
+ void setCacheSize(int pixels);
+
+ int mouseX() const;
+ int mouseY() const;
+
+ int idealWidth() const;
+ void setIdealWidth(int);
+ int idealHeight() const;
+ void setIdealHeight(int);
+
+
+ qreal progress() const;
+
+ QAction *reloadAction() const;
+ QAction *backAction() const;
+ QAction *forwardAction() const;
+ QAction *stopAction() const;
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+ QWebPage *page() const;
+ void setPage(QWebPage *page);
+
+ void load(const QNetworkRequest &request,
+ QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
+ const QByteArray &body = QByteArray());
+
+ QString html() const;
+
+ void setHtml(const QString &html, const QUrl &baseUrl = QUrl());
+ void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl());
+
+ QWebHistory *history() const;
+ QWebSettings *settings() const;
+ QObject *settingsObject() const;
+
+ QString status() const;
+
+Q_SIGNALS:
+ void idealWidthChanged();
+ void idealHeightChanged();
+ void urlChanged();
+ void interactiveChanged();
+ void progressChanged();
+ void titleChanged(const QString&);
+ void iconChanged();
+ void statusChanged();
+
+ void loadStarted();
+ void loadFinished();
+ void loadFailed();
+
+ void singleClick();
+ void doubleClick();
+
+private Q_SLOTS:
+ void updateCacheForVisibility();
+ void expandToWebPage();
+ void paintPage(const QRect&);
+ void doLoadProgress(int p);
+ void doLoadFinished(bool ok);
+ void setStatusBarMessage(const QString&);
+
+protected:
+ QFxWebView(QFxWebViewPrivate &dd, QFxItem *parent);
+
+ void drawContents(QPainter *, const QRect &);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent* event);
+ void keyReleaseEvent(QKeyEvent* event);
+ void timerEvent(QTimerEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private:
+ void init();
+ virtual void componentComplete();
+ Q_DISABLE_COPY(QFxWebView)
+ Q_DECLARE_PRIVATE(QFxWebView)
+};
+QML_DECLARE_TYPE(QFxWebView)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxwidgetcontainer.cpp b/src/declarative/fx/qfxwidgetcontainer.cpp
new file mode 100644
index 0000000..421c2f7
--- /dev/null
+++ b/src/declarative/fx/qfxwidgetcontainer.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxwidgetcontainer.h"
+#include <qsimplecanvas.h>
+#include <qgraphicswidget.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass WidgetContainer QFxWidgetContainer
+ \brief The WidgetContainer element allows you to add QGraphicsWidgets into Fluid UI elements.
+*/
+
+/*!
+ \internal
+ \class QFxWidgetContainer
+ \brief The QFxWidgetContainer class allows you to add QGraphicsWidgets into Fluid UI applications.
+*/
+
+QML_DEFINE_TYPE(QFxWidgetContainer, WidgetContainer)
+
+QFxWidgetContainer::QFxWidgetContainer(QFxItem *parent)
+: QFxItem(parent), _graphicsWidget(0)
+{
+}
+
+QFxWidgetContainer::~QFxWidgetContainer()
+{
+}
+
+QGraphicsWidget *QFxWidgetContainer::graphicsWidget() const
+{
+ return _graphicsWidget;
+}
+
+/*!
+ \qmlproperty QGraphicsWidget QFxWidgetContainer::graphicsWidget
+ The QGraphicsWidget associated with this element.
+*/
+void QFxWidgetContainer::setGraphicsWidget(QGraphicsWidget *widget)
+{
+ if (widget == _graphicsWidget)
+ return;
+
+ _graphicsWidget = widget;
+
+ QSimpleCanvas *c = canvas();
+ if (!c)
+ return;
+
+ if (c->canvasMode() != QSimpleCanvas::GraphicsView) {
+ qWarning("QFxWidgetContainer: Cannot add a widget to a non-graphicsview canvas. You might need to set QFX_USE_GRAPHICSVIEW=1");
+ return;
+ }
+
+ QGraphicsItem *item = (QGraphicsItem *)(*this);
+ _graphicsWidget->setParentItem(item);
+}
+
+void QFxWidgetContainer::canvasChanged()
+{
+ if (_graphicsWidget) {
+ QGraphicsWidget *w = _graphicsWidget;
+ _graphicsWidget = 0;
+ setGraphicsWidget(w);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxwidgetcontainer.h b/src/declarative/fx/qfxwidgetcontainer.h
new file mode 100644
index 0000000..cc36010
--- /dev/null
+++ b/src/declarative/fx/qfxwidgetcontainer.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXWIDGETCONTAINER_H
+#define QFXWIDGETCONTAINER_H
+
+#include <QtDeclarative/qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QGraphicsWidget;
+
+class Q_DECLARATIVE_EXPORT QFxWidgetContainer : public QFxItem
+{
+ Q_OBJECT
+
+ Q_CLASSINFO("DefaultProperty", "graphicsWidget")
+ Q_PROPERTY(QGraphicsWidget *graphicsWidget READ graphicsWidget WRITE setGraphicsWidget)
+
+public:
+ QFxWidgetContainer(QFxItem *parent = 0);
+ ~QFxWidgetContainer();
+
+ QGraphicsWidget *graphicsWidget() const;
+ void setGraphicsWidget(QGraphicsWidget *);
+
+protected:
+ virtual void canvasChanged();
+
+private:
+ QGraphicsWidget *_graphicsWidget;
+};
+QML_DECLARE_TYPE(QFxWidgetContainer)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXGRAPHICSWIDGET_H
diff --git a/src/declarative/opengl/glbasicshaders.cpp b/src/declarative/opengl/glbasicshaders.cpp
new file mode 100644
index 0000000..f546c0b
--- /dev/null
+++ b/src/declarative/opengl/glbasicshaders.cpp
@@ -0,0 +1,707 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "glbasicshaders.h"
+#include <QDebug>
+#include <QColor>
+
+
+QT_BEGIN_NAMESPACE
+SingleTextureVertexOpacityShader::SingleTextureVertexOpacityShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute lowp float myOpacity;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ varying lowp float myFragOpacity;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ myFragOpacity = myOpacity;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ varying mediump vec2 myTexCoord;\
+ varying lowp float myFragOpacity;\
+ void main(void)\
+ {\
+ mediump vec4 frag = texture2D(sampler2d,myTexCoord);\
+ gl_FragColor = vec4(frag.rgb, frag.a * myFragOpacity);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+ bindAttributeLocation("myOpacity", OpacityCoords);
+}
+
+bool SingleTextureVertexOpacityShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureVertexOpacityShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+BlurTextureShader::BlurTextureShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+#if 0
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform bool horizontal; \
+ uniform mediump float blurStep; \
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 accum = vec4(0, 0, 0, 0); \
+ mediump vec2 offset; \
+ if (horizontal) \
+ offset = vec2(blurStep, 0); \
+ else \
+ offset = vec2(0, blurStep); \
+ accum += texture2D(sampler2d, myTexCoord + 2.0 * offset); \
+ accum += 2.0 * texture2D(sampler2d, myTexCoord + 1.0 * offset); \
+ accum += 4.0 * texture2D(sampler2d, myTexCoord + 0.0 * offset); \
+ accum += 2.0 * texture2D(sampler2d, myTexCoord - 1.0 * offset); \
+ accum += texture2D(sampler2d, myTexCoord - 2.0 * offset); \
+ gl_FragColor = accum / 10.0; \
+ }"
+ );
+#else
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform bool horizontal; \
+ uniform mediump float blurStep; \
+ uniform int blurSteps; \
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 accum = vec4(0, 0, 0, 0); \
+ mediump vec2 offset; \
+ if (horizontal) \
+ offset = vec2(blurStep, 0); \
+ else \
+ offset = vec2(0, blurStep); \
+ mediump float sum = 0.0; \
+ for (int ii = 0; ii < blurSteps; ++ii) { \
+ mediump float frac = float(blurSteps - ii) / float(blurSteps); \
+ mediump vec2 coord = myTexCoord + -float(ii) * offset; \
+ if (coord.x >= 0.0 && coord.y >= 0.0 && coord.y <= 1.0 && coord.x <=1.0) \
+ accum += texture2D(sampler2d, coord) * frac; \
+ sum += frac; \
+ } \
+ for (int ii = 1; ii < blurSteps; ++ii) { \
+ mediump float frac = float(blurSteps - ii) / float(blurSteps); \
+ mediump vec2 coord = myTexCoord + float(ii) * offset; \
+ if (coord.x <= 1.0 && coord.y <= 1.0 && coord.x >= 0.0 && coord.y >= 0.0) \
+ accum += texture2D(sampler2d, coord) * frac; \
+ sum += frac; \
+ } \
+ gl_FragColor = accum / sum; \
+ }"
+ );
+#endif
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool BlurTextureShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ mode = uniformLocation("horizontal");
+ step = uniformLocation("blurStep");
+ steps = uniformLocation("blurSteps");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void BlurTextureShader::setStep(float f)
+{
+ setUniformValue(step, f);
+}
+
+void BlurTextureShader::setSteps(int s)
+{
+ setUniformValue(steps, s);
+}
+
+void BlurTextureShader::setMode(Mode m)
+{
+ if (m == Horizontal)
+ setUniformValue(mode, 1);
+ else
+ setUniformValue(mode, 0);
+}
+
+void BlurTextureShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+DualTextureBlendShader::DualTextureBlendShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ attribute mediump vec4 myBlendUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myBlendTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ myBlendTexCoord = myBlendUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform sampler2D sampler2dBlend;\
+ uniform lowp float myOpacity;\
+ uniform lowp float myBlend; \
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myBlendTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ mediump vec4 blendtex = texture2D(sampler2dBlend, myBlendTexCoord);\
+ gl_FragColor = mix(tex, blendtex, myBlend) * myOpacity; \
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+ bindAttributeLocation("myBlendUV", BlendTextureCoords);
+}
+
+bool DualTextureBlendShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ blend = uniformLocation("myBlend");
+ enable();
+ setUniformValue("sampler2d", 0);
+ setUniformValue("sampler2dBlend", 1);
+ disable();
+ return true;
+}
+
+void DualTextureBlendShader::setOpacity(GLfloat o)
+{
+ setUniformValue(opacity, o);
+}
+
+void DualTextureBlendShader::setBlend(GLfloat b)
+{
+ setUniformValue(blend, b);
+}
+
+void DualTextureBlendShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+DualTextureAddShader::DualTextureAddShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ attribute mediump vec4 myAddUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myAddTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ myAddTexCoord = myAddUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform sampler2D sampler2dAdd;\
+ uniform lowp float myOpacity;\
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myAddTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ mediump vec4 addtex = texture2D(sampler2dAdd, myAddTexCoord);\
+ tex = tex + vec4(addtex.rgb * addtex.a * tex.a, 0); \
+ tex = min(tex, vec4(1, 1, 1, 1)); \
+ gl_FragColor = vec4(tex.rgb, tex.a) * myOpacity;\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+ bindAttributeLocation("myAddUV", AddTextureCoords);
+}
+
+void DualTextureAddShader::setOpacity(GLfloat f)
+{
+ setUniformValue(opacity, f);
+}
+
+void DualTextureAddShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+bool DualTextureAddShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ enable();
+ setUniformValue("sampler2d", 0);
+ setUniformValue("sampler2dAdd", 1);
+ disable();
+ return true;
+}
+
+SingleTextureShader::SingleTextureShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_FragColor = texture2D(sampler2d,myTexCoord);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool SingleTextureShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+ConstantColorShader::ConstantColorShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ uniform mediump mat4 myPMVMatrix;\
+ attribute highp vec4 myVertex;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex; \
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform lowp vec4 myColor;\
+ void main(void)\
+ {\
+ gl_FragColor = myColor;\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+}
+
+void ConstantColorShader::setColor(const QColor &c)
+{
+ setUniformValue(color, c);
+}
+
+void ConstantColorShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+bool ConstantColorShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ color = uniformLocation("myColor");
+ return true;
+}
+
+ColorShader::ColorShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ uniform mediump mat4 myPMVMatrix;\
+ attribute highp vec4 myVertex;\
+ attribute lowp vec4 myColors;\
+ varying lowp vec4 myColor;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex; \
+ myColor = myColors; \
+ }"
+ );
+
+ frag.setSourceCode("\
+ varying lowp vec4 myColor;\
+ void main(void)\
+ {\
+ gl_FragColor = myColor;\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myColors", Colors);
+}
+
+void ColorShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+bool ColorShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ return true;
+}
+
+class GLBasicShadersPrivate
+{
+public:
+ GLBasicShadersPrivate();
+ ~GLBasicShadersPrivate();
+
+ BlurTextureShader *blurTexture;
+ SingleTextureShader *singleTexture;
+ SingleTextureOpacityShader *singleTextureOpacity;
+ DualTextureAddShader *dualTextureAdd;
+ SingleTextureShadowShader *singleTextureShadow;
+ SingleTextureVertexOpacityShader *singleTextureVertexOpacity;
+ ConstantColorShader *constantColor;
+ ColorShader *color;
+};
+
+GLBasicShadersPrivate::GLBasicShadersPrivate()
+: blurTexture(0), singleTexture(0), singleTextureOpacity(0),
+ dualTextureAdd(0), singleTextureShadow(0), singleTextureVertexOpacity(0),
+ constantColor(0), color(0)
+{
+}
+
+GLBasicShadersPrivate::~GLBasicShadersPrivate()
+{
+ delete blurTexture;
+ delete singleTexture;
+ delete singleTextureOpacity;
+ delete dualTextureAdd;
+ delete singleTextureVertexOpacity;
+ delete singleTextureShadow;
+ delete constantColor;
+ delete color;
+}
+
+GLBasicShaders::GLBasicShaders()
+: d(new GLBasicShadersPrivate)
+{
+}
+
+GLBasicShaders::~GLBasicShaders()
+{
+ delete d;
+}
+
+BlurTextureShader *GLBasicShaders::blurTexture()
+{
+ if (!d->blurTexture) d->blurTexture = new BlurTextureShader();
+ return d->blurTexture;
+}
+
+SingleTextureShader *GLBasicShaders::singleTexture()
+{
+ if (!d->singleTexture) d->singleTexture = new SingleTextureShader();
+ return d->singleTexture;
+}
+
+SingleTextureOpacityShader *GLBasicShaders::singleTextureOpacity()
+{
+ if (!d->singleTextureOpacity) d->singleTextureOpacity = new SingleTextureOpacityShader();
+ return d->singleTextureOpacity;
+}
+
+DualTextureAddShader *GLBasicShaders::dualTextureAdd()
+{
+ if (!d->dualTextureAdd) d->dualTextureAdd = new DualTextureAddShader();
+ return d->dualTextureAdd;
+}
+
+SingleTextureVertexOpacityShader *GLBasicShaders::singleTextureVertexOpacity()
+{
+ if (!d->singleTextureVertexOpacity) d->singleTextureVertexOpacity = new SingleTextureVertexOpacityShader();
+ return d->singleTextureVertexOpacity;
+}
+
+SingleTextureShadowShader *GLBasicShaders::singleTextureShadow()
+{
+ if (!d->singleTextureShadow) d->singleTextureShadow = new SingleTextureShadowShader();
+ return d->singleTextureShadow;
+}
+
+ConstantColorShader *GLBasicShaders::constantColor()
+{
+ if (!d->constantColor) d->constantColor = new ConstantColorShader();
+ return d->constantColor;
+}
+
+ColorShader *GLBasicShaders::color()
+{
+ if (!d->color) d->color = new ColorShader();
+ return d->color;
+}
+
+SingleTextureOpacityShader::SingleTextureOpacityShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform lowp float myOpacity;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ gl_FragColor = vec4(tex.rgb, myOpacity * tex.a);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool SingleTextureOpacityShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureOpacityShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+void SingleTextureOpacityShader::setOpacity(GLfloat f)
+{
+ setUniformValue(opacity, f);
+}
+
+SingleTextureShadowShader::SingleTextureShadowShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform lowp float myOpacity;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ gl_FragColor = vec4(0, 0, 0, myOpacity * tex.a * .75);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool SingleTextureShadowShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureShadowShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+void SingleTextureShadowShader::setOpacity(GLfloat f)
+{
+ setUniformValue(opacity, f);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/opengl/glbasicshaders.h b/src/declarative/opengl/glbasicshaders.h
new file mode 100644
index 0000000..7d358d8
--- /dev/null
+++ b/src/declarative/opengl/glbasicshaders.h
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLBASICSHADERS_H_
+#define _GLBASICSHADERS_H_
+
+#include <QtOpenGL/qglshaderprogram.h>
+#include <QtGui/qmatrix4x4.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class BlurTextureShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ BlurTextureShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ enum Mode { Horizontal, Vertical };
+ void setMode(Mode);
+ void setStep(float);
+ void setSteps(int);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint mode;
+ GLint step;
+ GLint steps;
+ GLint transform;
+};
+
+class SingleTextureShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+};
+
+class DualTextureBlendShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ DualTextureBlendShader();
+ enum { Vertices = 0,
+ TextureCoords = 1,
+ BlendTextureCoords = 2 };
+
+ void setOpacity(GLfloat);
+ void setBlend(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+ GLint blend;
+};
+
+class DualTextureAddShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ DualTextureAddShader();
+ enum { Vertices = 0,
+ TextureCoords = 1,
+ AddTextureCoords = 2 };
+
+ void setOpacity(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+};
+
+class SingleTextureOpacityShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureOpacityShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ void setOpacity(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+};
+
+class SingleTextureVertexOpacityShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureVertexOpacityShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1,
+ OpacityCoords = 2 };
+
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+};
+
+
+class SingleTextureShadowShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureShadowShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ void setOpacity(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+};
+
+
+class QColor;
+class ConstantColorShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ ConstantColorShader();
+
+ enum { Vertices = 0 };
+
+ void setColor(const QColor &);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint color;
+};
+
+class ColorShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ ColorShader();
+
+ enum { Vertices = 0, Colors = 1 };
+
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+};
+
+class GLBasicShadersPrivate;
+class GLBasicShaders
+{
+public:
+ GLBasicShaders();
+ virtual ~GLBasicShaders();
+
+ BlurTextureShader *blurTexture();
+ SingleTextureShader *singleTexture();
+ SingleTextureOpacityShader *singleTextureOpacity();
+ DualTextureAddShader *dualTextureAdd();
+ SingleTextureVertexOpacityShader *singleTextureVertexOpacity();
+ SingleTextureShadowShader *singleTextureShadow();
+ ConstantColorShader *constantColor();
+ ColorShader *color();
+
+private:
+ GLBasicShadersPrivate *d;
+};
+
+#endif // _GLBASICSHADERS_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/opengl/glheaders.h b/src/declarative/opengl/glheaders.h
new file mode 100644
index 0000000..fd1da18
--- /dev/null
+++ b/src/declarative/opengl/glheaders.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLHEADERS_H_
+#define _GLHEADERS_H_
+
+#include <QtDeclarative/qfxglobal.h>
+#define GL_GLEXT_PROTOTYPES 1
+#include <QtOpenGL/qgl.h>
+
+#endif // _GLHEADERS_H_
diff --git a/src/declarative/opengl/glsave.cpp b/src/declarative/opengl/glsave.cpp
new file mode 100644
index 0000000..125e81b
--- /dev/null
+++ b/src/declarative/opengl/glsave.cpp
@@ -0,0 +1 @@
+#include "glsave.h"
diff --git a/src/declarative/opengl/glsave.h b/src/declarative/opengl/glsave.h
new file mode 100644
index 0000000..ad6c0ec
--- /dev/null
+++ b/src/declarative/opengl/glsave.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLSAVE_H_
+#define _GLSAVE_H_
+
+#include <QtCore/qglobal.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtCore/QRect>
+#include "glheaders.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class GLSaveViewport
+{
+public:
+ GLSaveViewport()
+ {
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ }
+
+ ~GLSaveViewport()
+ {
+ glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+ }
+
+private:
+ Q_DISABLE_COPY(GLSaveViewport)
+ GLint viewport[4];
+};
+
+class GLSaveScissor
+{
+public:
+ GLSaveScissor()
+ {
+ enabled = glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_SCISSOR_BOX, box);
+ }
+
+ ~GLSaveScissor()
+ {
+ if (enabled)
+ glEnable(GL_SCISSOR_TEST);
+ else
+ glDisable(GL_SCISSOR_TEST);
+ glScissor(box[0], box[1], box[2], box[3]);
+ }
+
+ bool wasEnabled() const
+ {
+ return enabled == GL_TRUE;
+ }
+
+ QRect rect() const
+ {
+ return QRect(box[0], box[1], box[2], box[3]);
+ }
+
+private:
+ Q_DISABLE_COPY(GLSaveScissor)
+ GLint box[4];
+ GLboolean enabled;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // _GLSAVE_H_
diff --git a/src/declarative/opengl/gltexture.cpp b/src/declarative/opengl/gltexture.cpp
new file mode 100644
index 0000000..199b362
--- /dev/null
+++ b/src/declarative/opengl/gltexture.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gltexture.h"
+#include <QImage>
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \internal
+ \class GLTexture
+ \brief The GLTexture class simplifies the use of OpenGL textures.
+*/
+
+// Copied from QGLWidget::convertToGLFormat
+static QImage QGLWidget_convertToGLFormat(const QImage& img)
+{
+ QImage res = img.convertToFormat(QImage::Format_ARGB32);
+ res = res.mirrored();
+
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ // Qt has ARGB; OpenGL wants RGBA
+ for (int i=0; i < res.height(); i++) {
+ uint *p = (uint*)res.scanLine(i);
+ uint *end = p + res.width();
+ while (p < end) {
+ *p = (*p << 8) | ((*p >> 24) & 0xFF);
+ p++;
+ }
+ }
+ }
+ else {
+ // Qt has ARGB; OpenGL wants ABGR (i.e. RGBA backwards)
+ res = res.rgbSwapped();
+ }
+ return res;
+}
+class GLTexturePrivate
+{
+public:
+ GLTexturePrivate(GLTexture *_q)
+ : q(_q), texture(0), width(0), height(0),
+ horizWrap(GLTexture::Repeat), vertWrap(GLTexture::Repeat),
+ minFilter(GLTexture::Linear), magFilter(GLTexture::Linear)
+ {
+ }
+
+ GLTexture *q;
+ GLuint texture;
+ int width;
+ int height;
+ GLTexture::WrapMode horizWrap;
+ GLTexture::WrapMode vertWrap;
+ GLTexture::FilterMode minFilter;
+ GLTexture::FilterMode magFilter;
+
+ void genTexture();
+};
+
+void GLTexturePrivate::genTexture()
+{
+ if (texture)
+ return;
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
+ q->setHorizontalWrap(horizWrap);
+ q->setVerticalWrap(vertWrap);
+}
+
+GLTexture::GLTexture()
+: d(new GLTexturePrivate(this))
+{
+}
+
+GLTexture::GLTexture(const QString &file)
+: d(new GLTexturePrivate(this))
+{
+ QImage img(file);
+ if (!img.isNull())
+ setImage(img);
+}
+
+GLTexture::GLTexture(const QImage &img)
+: d(new GLTexturePrivate(this))
+{
+ setImage(img);
+}
+
+GLTexture::~GLTexture()
+{
+ if (d->texture)
+ glDeleteTextures(1, &d->texture);
+ delete d;
+ d = 0;
+}
+
+bool GLTexture::isNull() const
+{
+ return d->texture == 0;
+}
+
+void GLTexture::clear()
+{
+ if (d->texture) {
+ glDeleteTextures(1, &d->texture);
+ d->texture = 0;
+ d->width = 0;
+ d->height = 0;
+ }
+}
+
+static inline int npot(int size)
+{
+ size--;
+ size |= size >> 1;
+ size |= size >> 2;
+ size |= size >> 4;
+ size |= size >> 8;
+ size |= size >> 16;
+ size++;
+ return size;
+}
+
+/*!
+ Set the texture to \a img. If the texture has already been created (either
+ by explicitly setting the size, or by previously setting an image), it will
+ be destroyed and a new texture created with \a img's contents and size.
+ */
+void GLTexture::setImage(const QImage &img)
+{
+ if (img.isNull())
+ return;
+
+ d->genTexture();
+
+ //QImage dataImage = img.scaled(npot(img.width()), npot(img.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ QImage dataImage = QGLWidget_convertToGLFormat(img);
+
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(),
+ dataImage.height(), 0,
+ (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB,
+ GL_UNSIGNED_BYTE, dataImage.bits());
+ d->width = dataImage.width();
+ d->height = dataImage.height();
+
+#if 0
+ glGenerateMipmap(GL_TEXTURE_2D);
+ int e = glGetError();
+ if (d->magFilter == Linear)
+ setMagFilter(MipmapLinear);
+ if (d->minFilter == Linear)
+ setMinFilter((GLTexture::FilterMode)GL_LINEAR_MIPMAP_LINEAR);
+#endif
+}
+
+void GLTexture::copyImage(const QImage &img, const QPoint &point,
+ const QRect &srcRect)
+{
+ qFatal("Not implemented");
+ Q_UNUSED(img);
+ Q_UNUSED(point);
+ Q_UNUSED(srcRect);
+}
+
+QSize GLTexture::size() const
+{
+ return QSize(d->width, d->height);
+}
+
+int GLTexture::width() const
+{
+ return d->width;
+}
+
+int GLTexture::height() const
+{
+ return d->height;
+}
+
+/*!
+ Sets the \a size of the texture. This will destroy the current contents of
+ the texture. If an image has been assigned, it will need to be reassigned
+ using either setImage() or copyImage().
+
+ If size is invalid (width or height is less than or equal to 0) the texture
+ will be destroyed. This is equivalent to calling clear().
+*/
+void GLTexture::setSize(const QSize &size)
+{
+ if (size.width() <= 0 || size.height() <= 0) {
+ clear();
+ return;
+ }
+
+ d->genTexture();
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ d->width = size.width();
+ d->height = size.height();
+}
+
+GLTexture::WrapMode GLTexture::horizontalWrap() const
+{
+ return d->horizWrap;
+}
+
+GLTexture::WrapMode GLTexture::verticalWrap() const
+{
+ return d->vertWrap;
+}
+
+void GLTexture::setHorizontalWrap(WrapMode mode)
+{
+ d->horizWrap = mode;
+ if (d->texture) {
+ GLint last;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, last);
+ }
+}
+
+/*!
+ Set the veritcal wrap mode to \a mode.
+ */
+void GLTexture::setVerticalWrap(WrapMode mode)
+{
+ d->vertWrap = mode;
+ if (d->texture) {
+ GLint last;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, last);
+ }
+}
+
+GLTexture::FilterMode GLTexture::minFilter() const
+{
+ return d->minFilter;
+}
+
+GLTexture::FilterMode GLTexture::magFilter() const
+{
+ return d->magFilter;
+}
+
+void GLTexture::setMinFilter(FilterMode f)
+{
+ if (d->minFilter == f)
+ return;
+ d->minFilter = f;
+ if (d->texture) {
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, d->minFilter);
+ }
+}
+
+void GLTexture::setMagFilter(FilterMode f)
+{
+ if (d->magFilter == f)
+ return;
+ d->magFilter = f;
+ if (d->texture) {
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, d->magFilter);
+ }
+}
+
+GLuint GLTexture::texture() const
+{
+ return d->texture;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/opengl/gltexture.h b/src/declarative/opengl/gltexture.h
new file mode 100644
index 0000000..787c9a5
--- /dev/null
+++ b/src/declarative/opengl/gltexture.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLTEXTURE_H_
+#define _GLTEXTURE_H_
+
+#include <QtDeclarative/qfxglobal.h>
+
+#include <QtCore/QRect>
+#include <QtCore/QPoint>
+#include "glheaders.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QImage;
+class GLTexturePrivate;
+class Q_DECLARATIVE_EXPORT GLTexture
+{
+public:
+ GLTexture();
+ GLTexture(const QString &file);
+ GLTexture(const QImage &img);
+ virtual ~GLTexture();
+
+ bool isNull() const;
+ void clear();
+
+ void setImage(const QImage &);
+ void copyImage(const QImage &, const QPoint & = QPoint(0, 0), const QRect & = QRect());
+
+ int width() const;
+ int height() const;
+ QSize size() const;
+ void setSize(const QSize &);
+
+ enum WrapMode {
+ Repeat = GL_REPEAT,
+ ClampToEdge = GL_CLAMP_TO_EDGE,
+#if defined(QFX_RENDER_OPENGL2)
+ MirroredRepeat = GL_MIRRORED_REPEAT,
+#else
+ MirroredRepeat = Repeat
+#endif
+ };
+
+ WrapMode horizontalWrap() const;
+ WrapMode verticalWrap() const;
+ void setHorizontalWrap(WrapMode);
+ void setVerticalWrap(WrapMode);
+
+ enum FilterMode {
+ Nearest = GL_NEAREST,
+ Linear = GL_LINEAR,
+ MipmapLinear = GL_LINEAR_MIPMAP_LINEAR
+ };
+
+ FilterMode minFilter() const;
+ FilterMode magFilter() const;
+ void setMinFilter(FilterMode);
+ void setMagFilter(FilterMode);
+
+ GLuint texture() const;
+private:
+ Q_DISABLE_COPY(GLTexture)
+ GLTexturePrivate *d;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // _GLTEXTURE_H_
diff --git a/src/declarative/opengl/opengl.pri b/src/declarative/opengl/opengl.pri
new file mode 100644
index 0000000..c9ccefb
--- /dev/null
+++ b/src/declarative/opengl/opengl.pri
@@ -0,0 +1,20 @@
+DEPENDPATH += opengl
+INCLUDEPATH += opengl
+INCLUDEPATH += $$QMAKE_INCDIR_OPENGL
+QT += opengl
+
+contains(QT_CONFIG, opengles1) {
+ SOURCES += gltexture.cpp \
+ glsave.cpp
+
+ HEADERS += gltexture.h \
+ glsave.h
+} else:contains(QT_CONFIG, opengles2) {
+ SOURCES += gltexture.cpp \
+ glbasicshaders.cpp \
+ glsave.cpp
+
+ HEADERS += gltexture.h \
+ glbasicshaders.h \
+ glsave.h
+}
diff --git a/src/declarative/qml/parser/javascript.g b/src/declarative/qml/parser/javascript.g
new file mode 100644
index 0000000..8cabeea
--- /dev/null
+++ b/src/declarative/qml/parser/javascript.g
@@ -0,0 +1,2879 @@
+----------------------------------------------------------------------------
+--
+-- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+-- Contact: Qt Software Information (qt-info@nokia.com)
+--
+-- This file is part of the QtScript module of the Qt Toolkit.
+--
+-- $QT_BEGIN_LICENSE:LGPL$
+-- No Commercial Usage
+-- This file contains pre-release code and may not be distributed.
+-- You may use this file in accordance with the terms and conditions
+-- contained in the either Technology Preview License Agreement or the
+-- Beta Release License Agreement.
+--
+-- GNU Lesser General Public License Usage
+-- Alternatively, this file may be used under the terms of the GNU Lesser
+-- General Public License version 2.1 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.LGPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU Lesser General Public License version 2.1 requirements
+-- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+--
+-- In addition, as a special exception, Nokia gives you certain
+-- additional rights. These rights are described in the Nokia Qt LGPL
+-- Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+-- package.
+--
+-- GNU General Public License Usage
+-- Alternatively, this file may be used under the terms of the GNU
+-- General Public License version 3.0 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.GPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU General Public License version 3.0 requirements will be
+-- met: http://www.gnu.org/copyleft/gpl.html.
+--
+-- If you are unsure which license is appropriate for your use, please
+-- contact the sales department at qt-sales@nokia.com.
+-- $QT_END_LICENSE$
+--
+-- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+-- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+--
+----------------------------------------------------------------------------
+
+%parser JavaScriptGrammar
+%decl javascriptparser_p.h
+%impl javascriptparser.cpp
+%expect 2
+%expect-rr 2
+
+%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&="
+%token T_BREAK "break" T_CASE "case" T_CATCH "catch"
+%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue"
+%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/"
+%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
+%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
+%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
+%token T_FUNCTION "function" T_GE ">=" T_GT ">"
+%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
+%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
+%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{"
+%token T_LBRACKET "[" T_LE "<=" T_LPAREN "("
+%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<="
+%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--"
+%token T_NEW "new" T_NOT "!" T_NOT_EQ "!="
+%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|"
+%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+"
+%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?"
+%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
+%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")"
+%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*"
+%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal"
+%token T_PROPERTY "property" T_SIGNAL "signal"
+%token T_SWITCH "switch" T_THIS "this" T_THROW "throw"
+%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof"
+%token T_VAR "var" T_VOID "void" T_WHILE "while"
+%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
+%token T_NULL "null" T_TRUE "true" T_FALSE "false"
+%token T_CONST "const"
+%token T_DEBUGGER "debugger"
+%token T_RESERVED_WORD "reserved word"
+%token T_MULTILINE_STRING_LITERAL "multiline string literal"
+
+--- context keywords.
+%token T_PUBLIC "public"
+%token T_IMPORT "import"
+
+%nonassoc SHIFT_THERE
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY
+%nonassoc REDUCE_HERE
+
+%start UiProgram
+
+/.
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtDebug>
+
+#include <string.h>
+
+#include "javascriptengine_p.h"
+#include "javascriptlexer_p.h"
+#include "javascriptast_p.h"
+#include "javascriptnodepool_p.h"
+
+./
+
+/:
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+#ifndef JAVASCRIPTPARSER_P_H
+#define JAVASCRIPTPARSER_P_H
+
+#include "javascriptgrammar_p.h"
+#include "javascriptast_p.h"
+#include "javascriptengine_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace JavaScript {
+
+class Engine;
+class NameId;
+
+class Parser: protected $table
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ NameId *sval;
+ AST::ArgumentList *ArgumentList;
+ AST::CaseBlock *CaseBlock;
+ AST::CaseClause *CaseClause;
+ AST::CaseClauses *CaseClauses;
+ AST::Catch *Catch;
+ AST::DefaultClause *DefaultClause;
+ AST::ElementList *ElementList;
+ AST::Elision *Elision;
+ AST::ExpressionNode *Expression;
+ AST::Finally *Finally;
+ AST::FormalParameterList *FormalParameterList;
+ AST::FunctionBody *FunctionBody;
+ AST::FunctionDeclaration *FunctionDeclaration;
+ AST::Node *Node;
+ AST::PropertyName *PropertyName;
+ AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ AST::SourceElement *SourceElement;
+ AST::SourceElements *SourceElements;
+ AST::Statement *Statement;
+ AST::StatementList *StatementList;
+ AST::Block *Block;
+ AST::VariableDeclaration *VariableDeclaration;
+ AST::VariableDeclarationList *VariableDeclarationList;
+
+ AST::UiProgram *UiProgram;
+ AST::UiImportList *UiImportList;
+ AST::UiImport *UiImport;
+ AST::UiPublicMember *UiPublicMember;
+ AST::UiObjectDefinition *UiObjectDefinition;
+ AST::UiObjectInitializer *UiObjectInitializer;
+ AST::UiObjectBinding *UiObjectBinding;
+ AST::UiScriptBinding *UiScriptBinding;
+ AST::UiArrayBinding *UiArrayBinding;
+ AST::UiObjectMember *UiObjectMember;
+ AST::UiObjectMemberList *UiObjectMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ bool parse();
+
+ AST::UiProgram *ast()
+ { return program; }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+ AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
+
+protected:
+ Engine *driver;
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ AST::SourceLocation *location_stack;
+
+ AST::UiProgram *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ AST::SourceLocation loc;
+ };
+
+ double yylval;
+ AST::SourceLocation yylloc;
+ AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+} // end of namespace JavaScript
+
+
+:/
+
+
+/.
+
+#include "javascriptparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+using namespace JavaScript;
+
+QT_BEGIN_NAMESPACE
+
+void Parser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(Engine *driver, int token)
+{
+ return token == $table::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+Parser::Parser(Engine *engine):
+ driver(engine),
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+Parser::~Parser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
+{
+ QVarLengthArray<NameId *, 4> nameIds;
+ QVarLengthArray<AST::SourceLocation, 4> locations;
+
+ AST::ExpressionNode *it = expr;
+ while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) {
+ nameIds.append(m->name);
+ locations.append(m->identifierToken);
+ it = m->base;
+ }
+
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
+ AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name);
+ q->identifierToken = idExpr->identifierToken;
+
+ AST::UiQualifiedId *currentId = q;
+ for (int i = nameIds.size() - 1; i != -1; --i) {
+ currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]);
+ currentId->identifierToken = locations[i];
+ }
+
+ return currentId->finish();
+ }
+
+ return 0;
+}
+
+bool Parser::parse()
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ first_token = last_token = 0;
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+./
+
+--------------------------------------------------------------------------------------------------------
+-- Declarative UI
+--------------------------------------------------------------------------------------------------------
+
+UiProgram: UiImportListOpt UiRootMember ;
+/.
+case $rule_number: {
+ program = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+ sym(1).UiProgram = program;
+} break;
+./
+
+UiImportListOpt: Empty ;
+UiImportListOpt: UiImportList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+./
+
+UiImportList: UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+./
+
+UiImportList: UiImportList UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+./
+
+UiImport: T_IMPORT T_STRING_LITERAL T_AUTOMATIC_SEMICOLON;
+UiImport: T_IMPORT T_STRING_LITERAL T_SEMICOLON;
+/.
+case $rule_number: {
+ AST::UiImport *node = makeAstNode<AST::UiImport>(driver->nodePool(), sym(2).sval);
+ node->importToken = loc(1);
+ node->fileNameToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+Empty: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+UiRootMember: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMember ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMemberList UiObjectMember ;
+/.
+case $rule_number: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+./
+
+UiArrayMemberList: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ;
+/.
+case $rule_number: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(3).UiObjectMember);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectDefinition: UiQualifiedId UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiObjectDefinition ;
+
+UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(4).UiObjectMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiMultilineStringLiteral: T_MULTILINE_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UiMultilineStringStatement: UiMultilineStringLiteral T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+UiMultilineStringStatement: UiMultilineStringLiteral T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+
+UiObjectMember: UiQualifiedId T_COLON Expression UiObjectInitializer ;
+/.
+case $rule_number: {
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } else {
+ sym(1).Node = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2),
+ QLatin1String("Expected a type name after token `:'")));
+
+ return false; // ### recover
+ }
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON Block ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON EmptyStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON DebuggerStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON UiMultilineStringStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding?
+/.case $rule_number:./
+
+/.
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiPropertyType: T_VAR ;
+/.
+case $rule_number:
+./
+UiPropertyType: T_RESERVED_WORD ;
+/.
+case $rule_number: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+./
+
+UiPropertyType: T_IDENTIFIER ;
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+UiObjectMember: VariableStatement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+UiQualifiedId: T_RESERVED_WORD ;
+/.case $rule_number: ./
+
+UiQualifiedId: T_RETURN ;
+/.
+case $rule_number:
+{
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+JsIdentifier: T_IDENTIFIER;
+
+JsIdentifier: T_PROPERTY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_SIGNAL ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+--------------------------------------------------------------------------------------------------------
+-- Expressions
+--------------------------------------------------------------------------------------------------------
+
+PrimaryExpression: T_THIS ;
+/.
+case $rule_number: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NULL ;
+/.
+case $rule_number: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_TRUE ;
+/.
+case $rule_number: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_FALSE ;
+/.
+case $rule_number: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_EQ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET Elision T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ sym(4).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+-- PrimaryExpression: T_LBRACE T_RBRACE ;
+-- /.
+-- case $rule_number: {
+-- sym(1).Node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+-- } break;
+-- ./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LPAREN Expression T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiQualifiedId: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UiQualifiedId: UiQualifiedId T_DOT JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ElementList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression);
+} break;
+./
+
+ElementList: Elision AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression);
+} break;
+./
+
+ElementList: ElementList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList,
+ (AST::Elision *) 0, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ElementList: ElementList T_COMMA Elision AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(),
+ sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: Elision T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_IDENTIFIER %prec REDUCE_HERE ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_SIGNAL ;
+/.case $rule_number:./
+
+PropertyName: T_PROPERTY ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: ReservedIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ReservedIdentifier: T_BREAK ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CASE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CATCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONTINUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEFAULT ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DELETE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DO ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_ELSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FALSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FINALLY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FOR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FUNCTION ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_INSTANCEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NEW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NULL ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RETURN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_SWITCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THIS ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THROW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TYPEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VAR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VOID ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WHILE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONST ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEBUGGER ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RESERVED_WORD ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WITH ;
+/.
+case $rule_number:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+./
+
+PropertyIdentifier: JsIdentifier ;
+PropertyIdentifier: ReservedIdentifier ;
+
+MemberExpression: PrimaryExpression ;
+MemberExpression: FunctionExpression ;
+
+MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: MemberExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+NewExpression: MemberExpression ;
+
+NewExpression: T_NEW NewExpression ;
+/.
+case $rule_number: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ArgumentListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ArgumentListOpt: ArgumentList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+./
+
+ArgumentList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+./
+
+ArgumentList: ArgumentList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LeftHandSideExpression: NewExpression ;
+LeftHandSideExpression: CallExpression ;
+PostfixExpression: LeftHandSideExpression ;
+
+PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ;
+/.
+case $rule_number: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ;
+/.
+case $rule_number: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: PostfixExpression ;
+
+UnaryExpression: T_DELETE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_VOID UnaryExpression ;
+/.
+case $rule_number: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TYPEOF UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TILDE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_NOT UnaryExpression ;
+/.
+case $rule_number: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: UnaryExpression ;
+
+MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: MultiplicativeExpression ;
+
+AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: AdditiveExpression ;
+
+ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: ShiftExpression ;
+
+RelationalExpression: RelationalExpression T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_IN ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: ShiftExpression ;
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: RelationalExpression ;
+
+EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: RelationalExpressionNotIn ;
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpression: EqualityExpression ;
+
+BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpressionNotIn: EqualityExpressionNotIn ;
+
+BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpression: BitwiseANDExpression ;
+
+BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ;
+
+BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpression: BitwiseXORExpression ;
+
+BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ;
+
+BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpression: BitwiseORExpression ;
+
+LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ;
+
+LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpression: LogicalANDExpression ;
+
+LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpressionNotIn: LogicalANDExpressionNotIn ;
+
+LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpression: LogicalORExpression ;
+
+ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn ;
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpression: ConditionalExpression ;
+
+AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpressionNotIn: ConditionalExpressionNotIn ;
+
+AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentOperator: T_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+./
+
+AssignmentOperator: T_STAR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+./
+
+AssignmentOperator: T_DIVIDE_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+./
+
+AssignmentOperator: T_REMAINDER_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+./
+
+AssignmentOperator: T_PLUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+./
+
+AssignmentOperator: T_MINUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+./
+
+AssignmentOperator: T_LT_LT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+./
+
+AssignmentOperator: T_AND_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+./
+
+AssignmentOperator: T_XOR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+./
+
+AssignmentOperator: T_OR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+./
+
+Expression: AssignmentExpression ;
+
+Expression: Expression T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionOpt: Expression ;
+
+ExpressionNotIn: AssignmentExpressionNotIn ;
+
+ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionNotInOpt: ExpressionNotIn ;
+
+Statement: Block ;
+Statement: VariableStatement ;
+Statement: EmptyStatement ;
+Statement: ExpressionStatement ;
+Statement: IfStatement ;
+Statement: IterationStatement ;
+Statement: ContinueStatement ;
+Statement: BreakStatement ;
+Statement: ReturnStatement ;
+Statement: WithStatement ;
+Statement: LabelledStatement ;
+Statement: SwitchStatement ;
+Statement: ThrowStatement ;
+Statement: TryStatement ;
+Statement: DebuggerStatement ;
+
+
+Block: T_LBRACE StatementListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+StatementList: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+StatementList: StatementList Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+./
+
+StatementListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+StatementListOpt: StatementList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+./
+
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationKind: T_CONST ;
+/.
+case $rule_number: {
+ sym(1).ival = T_CONST;
+} break;
+./
+
+VariableDeclarationKind: T_VAR ;
+/.
+case $rule_number: {
+ sym(1).ival = T_VAR;
+} break;
+./
+
+VariableDeclarationList: VariableDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ;
+/.
+case $rule_number: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+./
+
+VariableDeclaration: JsIdentifier InitialiserOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Initialiser: T_EQ AssignmentExpression ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserOpt: Initialiser ;
+
+InitialiserNotIn: T_EQ AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserNotInOpt: InitialiserNotIn ;
+
+EmptyStatement: T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ExpressionStatement: Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ;
+/.
+case $rule_number: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+CaseClauses: CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+./
+
+CaseClauses: CaseClauses CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+./
+
+CaseClausesOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+CaseClausesOpt: CaseClauses ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+./
+
+CaseClause: T_CASE Expression T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+DefaultClause: T_DEFAULT T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_SIGNAL T_COLON Statement ;
+/.case $rule_number:./
+
+LabelledStatement: T_PROPERTY T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_IDENTIFIER T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ThrowStatement: T_THROW Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ;
+/.
+case $rule_number: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+Finally: T_FINALLY Block ;
+/.
+case $rule_number: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+DebuggerStatement: T_DEBUGGER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: FormalParameterList T_COMMA JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FormalParameterListOpt: FormalParameterList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+./
+
+FunctionBodyOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FunctionBodyOpt: FunctionBody ;
+
+FunctionBody: SourceElements ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+./
+
+--JavaScriptProgram: SourceElements ;
+--/.
+--case $rule_number: {
+-- sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ());
+-- driver->changeAbstractSyntaxTree(sym(1).Node);
+--} break;
+--./
+
+SourceElements: SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+./
+
+SourceElements: SourceElements SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+./
+
+SourceElement: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+SourceElement: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+./
+
+IdentifierOpt: ;
+/.
+case $rule_number: {
+ sym(1).sval = 0;
+} break;
+./
+
+IdentifierOpt: JsIdentifier ;
+
+PropertyNameAndValueListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+PropertyNameAndValueListOpt: PropertyNameAndValueList ;
+
+/.
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = QString::fromUtf8("Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = QString::fromUtf8("Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
+
+
+./
+/:
+QT_END_NAMESPACE
+
+
+
+#endif // JAVASCRIPTPARSER_P_H
+:/
diff --git a/src/declarative/qml/parser/javascriptast.cpp b/src/declarative/qml/parser/javascriptast.cpp
new file mode 100644
index 0000000..130229b
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptast.cpp
@@ -0,0 +1,952 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptast_p.h"
+
+
+
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+int NumericLiteral::suffixLength[] = {
+ 0, // noSuffix
+ 2, // emSuffix
+ 2, // exSuffix
+ 2, // pxSuffix
+ 2, // cmSuffix
+ 2, // mmSuffix
+ 2, // inSuffix
+ 2, // ptSuffix
+ 2, // pcSuffix
+ 3, // degSuffix
+ 3, // radSuffix
+ 4, // gradSuffix
+ 2, // msSuffix
+ 1, // sSuffix
+ 2, // hzSuffix
+ 3 // khzSuffix
+};
+
+const char *const NumericLiteral::suffixSpell[] = {
+ "",
+ "em",
+ "ex",
+ "px",
+ "cm",
+ "mm",
+ "in",
+ "pt",
+ "pc",
+ "deg",
+ "rad",
+ "grad",
+ "ms",
+ "s",
+ "hz",
+ "khz"
+};
+
+ExpressionNode *Node::expressionCast()
+{
+ return 0;
+}
+
+BinaryExpression *Node::binaryExpressionCast()
+{
+ return 0;
+}
+
+Statement *Node::statementCast()
+{
+ return 0;
+}
+
+ExpressionNode *ExpressionNode::expressionCast()
+{
+ return this;
+}
+
+BinaryExpression *BinaryExpression::binaryExpressionCast()
+{
+ return this;
+}
+
+Statement *Statement::statementCast()
+{
+ return this;
+}
+
+void NestedExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void ThisExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NullExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void TrueLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void FalseLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void RegExpLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(elements, visitor);
+ acceptChild(elision, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ObjectLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(properties, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ElementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ ElementList *it = this;
+ do {
+ acceptChild(it->elision, visitor);
+ acceptChild(it->expression, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Elision::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void PropertyNameAndValueList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ PropertyNameAndValueList *it = this;
+ do {
+ acceptChild(it->name, visitor);
+ acceptChild(it->value, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FieldMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ acceptChild(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CallExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ acceptChild(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArgumentList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ ArgumentList *it = this;
+ do {
+ acceptChild(it->expression, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DeleteExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VoidExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TypeOfExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryPlusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryMinusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TildeExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NotExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void BinaryExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(left, visitor);
+ acceptChild(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ConditionalExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(ok, visitor);
+ acceptChild(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Expression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(left, visitor);
+ acceptChild(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Block::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ StatementList *it = this;
+ do {
+ acceptChild(it->statement, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declarations, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclarationList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ VariableDeclarationList *it = this;
+ do {
+ acceptChild(it->declaration, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void EmptyStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ExpressionStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void IfStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(ok, visitor);
+ acceptChild(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DoWhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(initialiser, visitor);
+ acceptChild(condition, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declarations, visitor);
+ acceptChild(condition, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(initialiser, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declaration, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ContinueStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void BreakStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ReturnStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WithStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SwitchStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(block, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseBlock::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(clauses, visitor);
+ acceptChild(defaultClause, visitor);
+ acceptChild(moreClauses, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClauses::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ CaseClauses *it = this;
+ do {
+ acceptChild(it->clause, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DefaultClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LabelledStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ThrowStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TryStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ acceptChild(catchExpression, visitor);
+ acceptChild(finallyExpression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Catch::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Finally::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(formals, visitor);
+ acceptChild(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(formals, visitor);
+ acceptChild(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FormalParameterList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionBody::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Program::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SourceElements::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ SourceElements *it = this;
+ do {
+ acceptChild(it->element, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declaration, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DebuggerStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+
+void UiProgram::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = members; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiPublicMember::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectDefinition::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(qualifiedTypeNameId, visitor);
+ acceptChild(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectInitializer::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = members; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(qualifiedId, visitor);
+ acceptChild(qualifiedTypeNameId, visitor);
+ acceptChild(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiScriptBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(qualifiedId, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(qualifiedId, visitor);
+ for (UiObjectMemberList *it = members; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = this; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiQualifiedId::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImport::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImportList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(import, visitor);
+ acceptChild(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(sourceElement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+} } // namespace JavaScript::AST
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptast_p.h b/src/declarative/qml/parser/javascriptast_p.h
new file mode 100644
index 0000000..23d59e5
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptast_p.h
@@ -0,0 +1,2511 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTAST_P_H
+#define JAVASCRIPTAST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "javascriptastvisitor_p.h"
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+#define JAVASCRIPT_DECLARE_AST_NODE(name) \
+ enum { K = Kind_##name };
+
+namespace QSOperator // ### rename
+{
+
+enum Op {
+ Add,
+ And,
+ InplaceAnd,
+ Assign,
+ BitAnd,
+ BitOr,
+ BitXor,
+ InplaceSub,
+ Div,
+ InplaceDiv,
+ Equal,
+ Ge,
+ Gt,
+ In,
+ InplaceAdd,
+ InstanceOf,
+ Le,
+ LShift,
+ InplaceLeftShift,
+ Lt,
+ Mod,
+ InplaceMod,
+ Mul,
+ InplaceMul,
+ NotEqual,
+ Or,
+ InplaceOr,
+ RShift,
+ InplaceRightShift,
+ StrictEqual,
+ StrictNotEqual,
+ Sub,
+ URShift,
+ InplaceURightShift,
+ InplaceXor
+};
+
+} // namespace QSOperator
+
+namespace JavaScript {
+class NameId;
+namespace AST {
+
+template <typename _T1, typename _T2>
+_T1 cast(_T2 *ast)
+{
+ if (ast && ast->kind == static_cast<_T1>(0)->K)
+ return static_cast<_T1>(ast);
+
+ return 0;
+}
+
+class Node
+{
+public:
+ enum Kind {
+ Kind_Undefined,
+
+ Kind_ArgumentList,
+ Kind_ArrayLiteral,
+ Kind_ArrayMemberExpression,
+ Kind_BinaryExpression,
+ Kind_Block,
+ Kind_BreakStatement,
+ Kind_CallExpression,
+ Kind_CaseBlock,
+ Kind_CaseClause,
+ Kind_CaseClauses,
+ Kind_Catch,
+ Kind_ConditionalExpression,
+ Kind_ContinueStatement,
+ Kind_DebuggerStatement,
+ Kind_DefaultClause,
+ Kind_DeleteExpression,
+ Kind_DoWhileStatement,
+ Kind_ElementList,
+ Kind_Elision,
+ Kind_EmptyStatement,
+ Kind_Expression,
+ Kind_ExpressionStatement,
+ Kind_FalseLiteral,
+ Kind_FieldMemberExpression,
+ Kind_Finally,
+ Kind_ForEachStatement,
+ Kind_ForStatement,
+ Kind_FormalParameterList,
+ Kind_FunctionBody,
+ Kind_FunctionDeclaration,
+ Kind_FunctionExpression,
+ Kind_FunctionSourceElement,
+ Kind_IdentifierExpression,
+ Kind_IdentifierPropertyName,
+ Kind_IfStatement,
+ Kind_LabelledStatement,
+ Kind_LocalForEachStatement,
+ Kind_LocalForStatement,
+ Kind_NewExpression,
+ Kind_NewMemberExpression,
+ Kind_NotExpression,
+ Kind_NullExpression,
+ Kind_NumericLiteral,
+ Kind_NumericLiteralPropertyName,
+ Kind_ObjectLiteral,
+ Kind_PostDecrementExpression,
+ Kind_PostIncrementExpression,
+ Kind_PreDecrementExpression,
+ Kind_PreIncrementExpression,
+ Kind_Program,
+ Kind_PropertyName,
+ Kind_PropertyNameAndValueList,
+ Kind_RegExpLiteral,
+ Kind_ReturnStatement,
+ Kind_SourceElement,
+ Kind_SourceElements,
+ Kind_StatementList,
+ Kind_StatementSourceElement,
+ Kind_StringLiteral,
+ Kind_StringLiteralPropertyName,
+ Kind_SwitchStatement,
+ Kind_ThisExpression,
+ Kind_ThrowStatement,
+ Kind_TildeExpression,
+ Kind_TrueLiteral,
+ Kind_TryStatement,
+ Kind_TypeOfExpression,
+ Kind_UnaryMinusExpression,
+ Kind_UnaryPlusExpression,
+ Kind_VariableDeclaration,
+ Kind_VariableDeclarationList,
+ Kind_VariableStatement,
+ Kind_VoidExpression,
+ Kind_WhileStatement,
+ Kind_WithStatement,
+ Kind_NestedExpression,
+
+ Kind_UiArrayBinding,
+ Kind_UiImport,
+ Kind_UiImportList,
+ Kind_UiObjectBinding,
+ Kind_UiObjectDefinition,
+ Kind_UiObjectInitializer,
+ Kind_UiObjectMemberList,
+ Kind_UiProgram,
+ Kind_UiPublicMember,
+ Kind_UiQualifiedId,
+ Kind_UiScriptBinding,
+ Kind_UiSourceElement
+ };
+
+ inline Node()
+ : kind(Kind_Undefined) {}
+
+ virtual ~Node() {}
+
+ virtual ExpressionNode *expressionCast();
+ virtual BinaryExpression *binaryExpressionCast();
+ virtual Statement *statementCast();
+
+ inline void accept(Visitor *visitor)
+ {
+ if (visitor->preVisit(this)) {
+ accept0(visitor);
+ visitor->postVisit(this);
+ }
+ }
+
+ static void acceptChild(Node *node, Visitor *visitor)
+ {
+ if (node)
+ node->accept(visitor);
+ }
+
+ virtual void accept0(Visitor *visitor) = 0;
+
+// attributes
+ int kind;
+};
+
+class ExpressionNode: public Node
+{
+public:
+ ExpressionNode() {}
+ virtual ~ExpressionNode() {}
+
+ virtual ExpressionNode *expressionCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class Statement: public Node
+{
+public:
+ Statement() {}
+ virtual ~Statement() {}
+
+ virtual Statement *statementCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class NestedExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NestedExpression)
+
+ NestedExpression(ExpressionNode *expression)
+ : expression(expression)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lparenToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ThisExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ThisExpression)
+
+ ThisExpression() { kind = K; }
+ virtual ~ThisExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return thisToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return thisToken; }
+
+// attributes
+ SourceLocation thisToken;
+};
+
+class IdentifierExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(IdentifierExpression)
+
+ IdentifierExpression(NameId *n):
+ name (n) { kind = K; }
+
+ virtual ~IdentifierExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+// attributes
+ NameId *name;
+ SourceLocation identifierToken;
+};
+
+class NullExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NullExpression)
+
+ NullExpression() { kind = K; }
+ virtual ~NullExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return nullToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return nullToken; }
+
+// attributes
+ SourceLocation nullToken;
+};
+
+class TrueLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TrueLiteral)
+
+ TrueLiteral() { kind = K; }
+ virtual ~TrueLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return trueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return trueToken; }
+
+// attributes
+ SourceLocation trueToken;
+};
+
+class FalseLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FalseLiteral)
+
+ FalseLiteral() { kind = K; }
+ virtual ~FalseLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return falseToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return falseToken; }
+
+// attributes
+ SourceLocation falseToken;
+};
+
+class NumericLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NumericLiteral)
+
+ enum Suffix { // ### keep it in sync with the Suffix enum in javascriptlexer_p.h
+ noSuffix,
+ emSuffix,
+ exSuffix,
+ pxSuffix,
+ cmSuffix,
+ mmSuffix,
+ inSuffix,
+ ptSuffix,
+ pcSuffix,
+ degSuffix,
+ radSuffix,
+ gradSuffix,
+ msSuffix,
+ sSuffix,
+ hzSuffix,
+ khzSuffix
+ };
+
+ static int suffixLength[];
+ static const char *const suffixSpell[];
+
+ NumericLiteral(double v, int suffix):
+ value(v), suffix(suffix) { kind = K; }
+ virtual ~NumericLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ double value;
+ int suffix;
+ SourceLocation literalToken;
+};
+
+class StringLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StringLiteral)
+
+ StringLiteral(NameId *v):
+ value (v) { kind = K; }
+
+ virtual ~StringLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ NameId *value;
+ SourceLocation literalToken;
+};
+
+class RegExpLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(RegExpLiteral)
+
+ RegExpLiteral(NameId *p, int f):
+ pattern (p), flags (f) { kind = K; }
+
+ virtual ~RegExpLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ NameId *pattern;
+ int flags;
+ SourceLocation literalToken;
+};
+
+class ArrayLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ArrayLiteral)
+
+ ArrayLiteral(Elision *e):
+ elements (0), elision (e)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts):
+ elements (elts), elision (0)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts, Elision *e):
+ elements (elts), elision (e)
+ { kind = K; }
+
+ virtual ~ArrayLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbracketToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ElementList *elements;
+ Elision *elision;
+ SourceLocation lbracketToken;
+ SourceLocation commaToken;
+ SourceLocation rbracketToken;
+};
+
+class ObjectLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ObjectLiteral)
+
+ ObjectLiteral():
+ properties (0) { kind = K; }
+
+ ObjectLiteral(PropertyNameAndValueList *plist):
+ properties (plist) { kind = K; }
+
+ virtual ~ObjectLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ PropertyNameAndValueList *properties;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class ElementList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ElementList)
+
+ ElementList(Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr), next (this)
+ { kind = K; }
+
+ ElementList(ElementList *previous, Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ElementList() {}
+
+ inline ElementList *finish ()
+ {
+ ElementList *front = next;
+ next = 0;
+ return front;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Elision *elision;
+ ExpressionNode *expression;
+ ElementList *next;
+ SourceLocation commaToken;
+};
+
+class Elision: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Elision)
+
+ Elision():
+ next (this) { kind = K; }
+
+ Elision(Elision *previous)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~Elision() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline Elision *finish ()
+ {
+ Elision *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Elision *next;
+ SourceLocation commaToken;
+};
+
+class PropertyNameAndValueList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PropertyNameAndValueList)
+
+ PropertyNameAndValueList(PropertyName *n, ExpressionNode *v):
+ name (n), value (v), next (this)
+ { kind = K; }
+
+ PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v):
+ name (n), value (v)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~PropertyNameAndValueList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline PropertyNameAndValueList *finish ()
+ {
+ PropertyNameAndValueList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ PropertyName *name;
+ ExpressionNode *value;
+ PropertyNameAndValueList *next;
+ SourceLocation colonToken;
+ SourceLocation commaToken;
+};
+
+class PropertyName: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PropertyName)
+
+ PropertyName() { kind = K; }
+ virtual ~PropertyName() {}
+
+// attributes
+ SourceLocation propertyNameToken;
+};
+
+class IdentifierPropertyName: public PropertyName
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(IdentifierPropertyName)
+
+ IdentifierPropertyName(NameId *n):
+ id (n) { kind = K; }
+
+ virtual ~IdentifierPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *id;
+};
+
+class StringLiteralPropertyName: public PropertyName
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StringLiteralPropertyName)
+
+ StringLiteralPropertyName(NameId *n):
+ id (n) { kind = K; }
+ virtual ~StringLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *id;
+};
+
+class NumericLiteralPropertyName: public PropertyName
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NumericLiteralPropertyName)
+
+ NumericLiteralPropertyName(double n):
+ id (n) { kind = K; }
+ virtual ~NumericLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ double id;
+};
+
+class ArrayMemberExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ArrayMemberExpression)
+
+ ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e):
+ base (b), expression (e)
+ { kind = K; }
+
+ virtual ~ArrayMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ExpressionNode *base;
+ ExpressionNode *expression;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+class FieldMemberExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FieldMemberExpression)
+
+ FieldMemberExpression(ExpressionNode *b, NameId *n):
+ base (b), name (n)
+ { kind = K; }
+
+ virtual ~FieldMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+ // attributes
+ ExpressionNode *base;
+ NameId *name;
+ SourceLocation dotToken;
+ SourceLocation identifierToken;
+};
+
+class NewMemberExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NewMemberExpression)
+
+ NewMemberExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~NewMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+ // attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation newToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class NewExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NewExpression)
+
+ NewExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NewExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation newToken;
+};
+
+class CallExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CallExpression)
+
+ CallExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~CallExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ArgumentList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ArgumentList)
+
+ ArgumentList(ExpressionNode *e):
+ expression (e), next (this)
+ { kind = K; }
+
+ ArgumentList(ArgumentList *previous, ExpressionNode *e):
+ expression (e)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ArgumentList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline ArgumentList *finish ()
+ {
+ ArgumentList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ ExpressionNode *expression;
+ ArgumentList *next;
+ SourceLocation commaToken;
+};
+
+class PostIncrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PostIncrementExpression)
+
+ PostIncrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return incrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation incrementToken;
+};
+
+class PostDecrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PostDecrementExpression)
+
+ PostDecrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return decrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation decrementToken;
+};
+
+class DeleteExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DeleteExpression)
+
+ DeleteExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+ virtual ~DeleteExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return deleteToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation deleteToken;
+};
+
+class VoidExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VoidExpression)
+
+ VoidExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~VoidExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return voidToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation voidToken;
+};
+
+class TypeOfExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TypeOfExpression)
+
+ TypeOfExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TypeOfExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return typeofToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation typeofToken;
+};
+
+class PreIncrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PreIncrementExpression)
+
+ PreIncrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return incrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation incrementToken;
+};
+
+class PreDecrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PreDecrementExpression)
+
+ PreDecrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return decrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation decrementToken;
+};
+
+class UnaryPlusExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UnaryPlusExpression)
+
+ UnaryPlusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryPlusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return plusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation plusToken;
+};
+
+class UnaryMinusExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UnaryMinusExpression)
+
+ UnaryMinusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryMinusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return minusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation minusToken;
+};
+
+class TildeExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TildeExpression)
+
+ TildeExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TildeExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tildeToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation tildeToken;
+};
+
+class NotExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NotExpression)
+
+ NotExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NotExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return notToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation notToken;
+};
+
+class BinaryExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(BinaryExpression)
+
+ BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r):
+ left (l), op (o), right (r)
+ { kind = K; }
+
+ virtual ~BinaryExpression() {}
+
+ virtual BinaryExpression *binaryExpressionCast();
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ int op;
+ ExpressionNode *right;
+ SourceLocation operatorToken;
+};
+
+class ConditionalExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ConditionalExpression)
+
+ ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~ConditionalExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return ko->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ ExpressionNode *ok;
+ ExpressionNode *ko;
+ SourceLocation questionToken;
+ SourceLocation colonToken;
+};
+
+class Expression: public ExpressionNode // ### rename
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Expression)
+
+ Expression(ExpressionNode *l, ExpressionNode *r):
+ left (l), right (r) { kind = K; }
+
+ virtual ~Expression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ ExpressionNode *right;
+ SourceLocation commaToken;
+};
+
+class Block: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Block)
+
+ Block(StatementList *slist):
+ statements (slist) { kind = K; }
+
+ virtual ~Block() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+ // attributes
+ StatementList *statements;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class StatementList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StatementList)
+
+ StatementList(Statement *stmt):
+ statement (stmt), next (this)
+ { kind = K; }
+
+ StatementList(StatementList *previous, Statement *stmt):
+ statement (stmt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~StatementList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline StatementList *finish ()
+ {
+ StatementList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Statement *statement;
+ StatementList *next;
+};
+
+class VariableStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VariableStatement)
+
+ VariableStatement(VariableDeclarationList *vlist):
+ declarations (vlist)
+ { kind = K; }
+
+ virtual ~VariableStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return declarationKindToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ VariableDeclarationList *declarations;
+ SourceLocation declarationKindToken;
+ SourceLocation semicolonToken;
+};
+
+class VariableDeclaration: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VariableDeclaration)
+
+ VariableDeclaration(NameId *n, ExpressionNode *e):
+ name (n), expression (e), readOnly(false)
+ { kind = K; }
+
+ virtual ~VariableDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ ExpressionNode *expression;
+ bool readOnly;
+ SourceLocation identifierToken;
+};
+
+class VariableDeclarationList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VariableDeclarationList)
+
+ VariableDeclarationList(VariableDeclaration *decl):
+ declaration (decl), next (this)
+ { kind = K; }
+
+ VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl):
+ declaration (decl)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~VariableDeclarationList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline VariableDeclarationList *finish (bool readOnly)
+ {
+ VariableDeclarationList *front = next;
+ next = 0;
+ if (readOnly) {
+ VariableDeclarationList *vdl;
+ for (vdl = front; vdl != 0; vdl = vdl->next)
+ vdl->declaration->readOnly = true;
+ }
+ return front;
+ }
+
+// attributes
+ VariableDeclaration *declaration;
+ VariableDeclarationList *next;
+ SourceLocation commaToken;
+};
+
+class EmptyStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(EmptyStatement)
+
+ EmptyStatement() { kind = K; }
+ virtual ~EmptyStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return semicolonToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation semicolonToken;
+};
+
+class ExpressionStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ExpressionStatement)
+
+ ExpressionStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ExpressionStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation semicolonToken;
+};
+
+class IfStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(IfStatement)
+
+ IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~IfStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return ifToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (ko)
+ return ko->lastSourceLocation();
+
+ return ok->lastSourceLocation();
+ }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *ok;
+ Statement *ko;
+ SourceLocation ifToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation elseToken;
+};
+
+class DoWhileStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DoWhileStatement)
+
+ DoWhileStatement(Statement *stmt, ExpressionNode *e):
+ statement (stmt), expression (e)
+ { kind = K; }
+
+ virtual ~DoWhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return doToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ Statement *statement;
+ ExpressionNode *expression;
+ SourceLocation doToken;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation semicolonToken;
+};
+
+class WhileStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(WhileStatement)
+
+ WhileStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return whileToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ForStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ForStatement)
+
+ ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ initialiser (i), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class LocalForStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(LocalForStatement)
+
+ LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ declarations (vlist), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclarationList *declarations;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class ForEachStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ForEachStatement)
+
+ ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt):
+ initialiser (i), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class LocalForEachStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(LocalForEachStatement)
+
+ LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt):
+ declaration (v), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclaration *declaration;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class ContinueStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ContinueStatement)
+
+ ContinueStatement(NameId *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~ContinueStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return continueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ NameId *label;
+ SourceLocation continueToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class BreakStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(BreakStatement)
+
+ BreakStatement(NameId *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~BreakStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return breakToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ NameId *label;
+ SourceLocation breakToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class ReturnStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ReturnStatement)
+
+ ReturnStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ReturnStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return returnToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation returnToken;
+ SourceLocation semicolonToken;
+};
+
+class WithStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(WithStatement)
+
+ WithStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WithStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return withToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation withToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class CaseBlock: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CaseBlock)
+
+ CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0):
+ clauses (c), defaultClause (d), moreClauses (r)
+ { kind = K; }
+
+ virtual ~CaseBlock() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ CaseClauses *clauses;
+ DefaultClause *defaultClause;
+ CaseClauses *moreClauses;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class SwitchStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(SwitchStatement)
+
+ SwitchStatement(ExpressionNode *e, CaseBlock *b):
+ expression (e), block (b)
+ { kind = K; }
+
+ virtual ~SwitchStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return switchToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return block->rbraceToken; }
+
+// attributes
+ ExpressionNode *expression;
+ CaseBlock *block;
+ SourceLocation switchToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class CaseClauses: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CaseClauses)
+
+ CaseClauses(CaseClause *c):
+ clause (c), next (this)
+ { kind = K; }
+
+ CaseClauses(CaseClauses *previous, CaseClause *c):
+ clause (c)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~CaseClauses() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline CaseClauses *finish ()
+ {
+ CaseClauses *front = next;
+ next = 0;
+ return front;
+ }
+
+//attributes
+ CaseClause *clause;
+ CaseClauses *next;
+};
+
+class CaseClause: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CaseClause)
+
+ CaseClause(ExpressionNode *e, StatementList *slist):
+ expression (e), statements (slist)
+ { kind = K; }
+
+ virtual ~CaseClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ ExpressionNode *expression;
+ StatementList *statements;
+ SourceLocation caseToken;
+ SourceLocation colonToken;
+};
+
+class DefaultClause: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DefaultClause)
+
+ DefaultClause(StatementList *slist):
+ statements (slist)
+ { kind = K; }
+
+ virtual ~DefaultClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ StatementList *statements;
+ SourceLocation defaultToken;
+ SourceLocation colonToken;
+};
+
+class LabelledStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(LabelledStatement)
+
+ LabelledStatement(NameId *l, Statement *stmt):
+ label (l), statement (stmt)
+ { kind = K; }
+
+ virtual ~LabelledStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ NameId *label;
+ Statement *statement;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+};
+
+class ThrowStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ThrowStatement)
+
+ ThrowStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ThrowStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return throwToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ ExpressionNode *expression;
+ SourceLocation throwToken;
+ SourceLocation semicolonToken;
+};
+
+class Catch: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Catch)
+
+ Catch(NameId *n, Block *stmt):
+ name (n), statement (stmt)
+ { kind = K; }
+
+ virtual ~Catch() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ Block *statement;
+ SourceLocation catchToken;
+ SourceLocation lparenToken;
+ SourceLocation identifierToken;
+ SourceLocation rparenToken;
+};
+
+class Finally: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Finally)
+
+ Finally(Block *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~Finally() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Block *statement;
+ SourceLocation finallyToken;
+};
+
+class TryStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TryStatement)
+
+ TryStatement(Statement *stmt, Catch *c, Finally *f):
+ statement (stmt), catchExpression (c), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Finally *f):
+ statement (stmt), catchExpression (0), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Catch *c):
+ statement (stmt), catchExpression (c), finallyExpression (0)
+ { kind = K; }
+
+ virtual ~TryStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tryToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (finallyExpression)
+ return finallyExpression->statement->rbraceToken;
+ else if (catchExpression)
+ return catchExpression->statement->rbraceToken;
+
+ return statement->lastSourceLocation();
+ }
+
+// attributes
+ Statement *statement;
+ Catch *catchExpression;
+ Finally *finallyExpression;
+ SourceLocation tryToken;
+};
+
+class FunctionExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionExpression)
+
+ FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b):
+ name (n), formals (f), body (b)
+ { kind = K; }
+
+ virtual ~FunctionExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return functionToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ NameId *name;
+ FormalParameterList *formals;
+ FunctionBody *body;
+ SourceLocation functionToken;
+ SourceLocation identifierToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class FunctionDeclaration: public FunctionExpression
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionDeclaration)
+
+ FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b):
+ FunctionExpression(n, f, b)
+ { kind = K; }
+
+ virtual ~FunctionDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+};
+
+class FormalParameterList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FormalParameterList)
+
+ FormalParameterList(NameId *n):
+ name (n), next (this)
+ { kind = K; }
+
+ FormalParameterList(FormalParameterList *previous, NameId *n):
+ name (n)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~FormalParameterList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline FormalParameterList *finish ()
+ {
+ FormalParameterList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ NameId *name;
+ FormalParameterList *next;
+ SourceLocation commaToken;
+ SourceLocation identifierToken;
+};
+
+class FunctionBody: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionBody)
+
+ FunctionBody(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~FunctionBody() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class Program: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Program)
+
+ Program(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~Program() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class SourceElements: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(SourceElements)
+
+ SourceElements(SourceElement *elt):
+ element (elt), next (this)
+ { kind = K; }
+
+ SourceElements(SourceElements *previous, SourceElement *elt):
+ element (elt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~SourceElements() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline SourceElements *finish ()
+ {
+ SourceElements *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ SourceElement *element;
+ SourceElements *next;
+};
+
+class SourceElement: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(SourceElement)
+
+ inline SourceElement()
+ { kind = K; }
+
+ virtual ~SourceElement() {}
+};
+
+class FunctionSourceElement: public SourceElement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionSourceElement)
+
+ FunctionSourceElement(FunctionDeclaration *f):
+ declaration (f)
+ { kind = K; }
+
+ virtual ~FunctionSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ FunctionDeclaration *declaration;
+};
+
+class StatementSourceElement: public SourceElement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StatementSourceElement)
+
+ StatementSourceElement(Statement *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~StatementSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Statement *statement;
+};
+
+class DebuggerStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DebuggerStatement)
+
+ DebuggerStatement()
+ { kind = K; }
+
+ virtual ~DebuggerStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return debuggerToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation debuggerToken;
+ SourceLocation semicolonToken;
+};
+
+class UiProgram: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiProgram)
+
+ UiProgram(UiImportList *imports, UiObjectMemberList *members)
+ : imports(imports), members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImportList *imports;
+ UiObjectMemberList *members;
+};
+
+class UiQualifiedId: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiQualifiedId)
+
+ UiQualifiedId(NameId *name)
+ : next(this), name(name)
+ { kind = K; }
+
+ UiQualifiedId(UiQualifiedId *previous, NameId *name)
+ : name(name)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~UiQualifiedId() {}
+
+ UiQualifiedId *finish()
+ {
+ UiQualifiedId *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *next;
+ NameId *name;
+ SourceLocation identifierToken;
+};
+
+class UiImport: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiImport)
+
+ UiImport(NameId *fileName)
+ : fileName(fileName)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *fileName;
+ SourceLocation importToken;
+ SourceLocation fileNameToken;
+ SourceLocation semicolonToken;
+};
+
+class UiImportList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiImportList)
+
+ UiImportList(UiImport *import)
+ : import(import),
+ next(this)
+ { kind = K; }
+
+ UiImportList(UiImportList *previous, UiImport *import)
+ : import(import)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ UiImportList *finish()
+ {
+ UiImportList *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImport *import;
+ UiImportList *next;
+};
+
+class UiObjectMember: public Node
+{
+public:
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class UiObjectMemberList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectMemberList)
+
+ UiObjectMemberList(UiObjectMember *member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+ UiObjectMemberList *finish()
+ {
+ UiObjectMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiObjectMemberList *next;
+ UiObjectMember *member;
+};
+
+class UiObjectInitializer: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectInitializer)
+
+ UiObjectInitializer(UiObjectMemberList *members)
+ : members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lbraceToken;
+ UiObjectMemberList *members;
+ SourceLocation rbraceToken;
+};
+
+class UiPublicMember: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiPublicMember)
+
+ UiPublicMember(NameId *memberType,
+ NameId *name)
+ : type(Property), memberType(memberType), name(name), expression(0), isDefaultMember(false)
+ { kind = K; }
+
+ UiPublicMember(NameId *memberType,
+ NameId *name,
+ ExpressionNode *expression)
+ : type(Property), memberType(memberType), name(name), expression(expression), isDefaultMember(false)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (defaultToken.isValid())
+ return defaultToken;
+
+ return propertyToken;
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ return semicolonToken;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ enum { Signal, Property } type;
+ NameId *memberType;
+ NameId *name;
+ ExpressionNode *expression;
+ bool isDefaultMember;
+ SourceLocation defaultToken;
+ SourceLocation propertyToken;
+ SourceLocation typeToken;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+ SourceLocation semicolonToken;
+};
+
+class UiObjectDefinition: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectDefinition)
+
+ UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId,
+ UiObjectInitializer *initializer)
+ : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedTypeNameId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return initializer->rbraceToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedTypeNameId;
+ UiObjectInitializer *initializer;
+};
+
+class UiSourceElement: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiSourceElement)
+
+ UiSourceElement(Node *sourceElement)
+ : sourceElement(sourceElement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->firstSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->firstSourceLocation();
+
+ return SourceLocation();
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->lastSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->lastSourceLocation();
+
+ return SourceLocation();
+ }
+
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Node *sourceElement;
+};
+
+class UiObjectBinding: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectBinding)
+
+ UiObjectBinding(UiQualifiedId *qualifiedId,
+ UiQualifiedId *qualifiedTypeNameId,
+ UiObjectInitializer *initializer)
+ : qualifiedId(qualifiedId),
+ qualifiedTypeNameId(qualifiedTypeNameId),
+ initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return initializer->rbraceToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiQualifiedId *qualifiedTypeNameId;
+ UiObjectInitializer *initializer;
+ SourceLocation colonToken;
+};
+
+class UiScriptBinding: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiScriptBinding)
+
+ UiScriptBinding(UiQualifiedId *qualifiedId,
+ Statement *statement)
+ : qualifiedId(qualifiedId),
+ statement(statement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ Statement *statement;
+ SourceLocation colonToken;
+};
+
+class UiArrayBinding: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiArrayBinding)
+
+ UiArrayBinding(UiQualifiedId *qualifiedId,
+ UiObjectMemberList *members)
+ : qualifiedId(qualifiedId),
+ members(members)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbracketToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiObjectMemberList *members;
+ SourceLocation colonToken;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+} } // namespace AST
+
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptastfwd_p.h b/src/declarative/qml/parser/javascriptastfwd_p.h
new file mode 100644
index 0000000..822a2d7
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptastfwd_p.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTAST_FWD_P_H
+#define JAVASCRIPTAST_FWD_P_H
+
+#include <QtCore/qglobal.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+class SourceLocation
+{
+public:
+ SourceLocation(quint32 offset = 0, quint32 length = 0)
+ : offset(offset), length(length),
+ startLine(0), startColumn(0)
+ { }
+
+ bool isValid() const { return length != 0; }
+
+ quint32 begin() const { return offset; }
+ quint32 end() const { return offset + length; }
+
+// attributes
+ // ### encode
+ quint32 offset;
+ quint32 length;
+ quint32 startLine;
+ quint32 startColumn;
+};
+
+class Visitor;
+class Node;
+class ExpressionNode;
+class Statement;
+class ThisExpression;
+class IdentifierExpression;
+class NullExpression;
+class TrueLiteral;
+class FalseLiteral;
+class NumericLiteral;
+class StringLiteral;
+class RegExpLiteral;
+class ArrayLiteral;
+class ObjectLiteral;
+class ElementList;
+class Elision;
+class PropertyNameAndValueList;
+class PropertyName;
+class IdentifierPropertyName;
+class StringLiteralPropertyName;
+class NumericLiteralPropertyName;
+class ArrayMemberExpression;
+class FieldMemberExpression;
+class NewMemberExpression;
+class NewExpression;
+class CallExpression;
+class ArgumentList;
+class PostIncrementExpression;
+class PostDecrementExpression;
+class DeleteExpression;
+class VoidExpression;
+class TypeOfExpression;
+class PreIncrementExpression;
+class PreDecrementExpression;
+class UnaryPlusExpression;
+class UnaryMinusExpression;
+class TildeExpression;
+class NotExpression;
+class BinaryExpression;
+class ConditionalExpression;
+class Expression; // ### rename
+class Block;
+class StatementList;
+class VariableStatement;
+class VariableDeclarationList;
+class VariableDeclaration;
+class EmptyStatement;
+class ExpressionStatement;
+class IfStatement;
+class DoWhileStatement;
+class WhileStatement;
+class ForStatement;
+class LocalForStatement;
+class ForEachStatement;
+class LocalForEachStatement;
+class ContinueStatement;
+class BreakStatement;
+class ReturnStatement;
+class WithStatement;
+class SwitchStatement;
+class CaseBlock;
+class CaseClauses;
+class CaseClause;
+class DefaultClause;
+class LabelledStatement;
+class ThrowStatement;
+class TryStatement;
+class Catch;
+class Finally;
+class FunctionDeclaration;
+class FunctionExpression;
+class FormalParameterList;
+class FunctionBody;
+class Program;
+class SourceElements;
+class SourceElement;
+class FunctionSourceElement;
+class StatementSourceElement;
+class DebuggerStatement;
+class NestedExpression;
+
+// ui elements
+class UiProgram;
+class UiImportList;
+class UiImport;
+class UiPublicMember;
+class UiObjectDefinition;
+class UiObjectInitializer;
+class UiObjectBinding;
+class UiScriptBinding;
+class UiSourceElement;
+class UiArrayBinding;
+class UiObjectMember;
+class UiObjectMemberList;
+class UiQualifiedId;
+
+} } // namespace AST
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptastvisitor.cpp b/src/declarative/qml/parser/javascriptastvisitor.cpp
new file mode 100644
index 0000000..eac291d
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptastvisitor.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+} } // namespace JavaScript::AST
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/parser/javascriptastvisitor_p.h b/src/declarative/qml/parser/javascriptastvisitor_p.h
new file mode 100644
index 0000000..81df364
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptastvisitor_p.h
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTASTVISITOR_P_H
+#define JAVASCRIPTASTVISITOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "javascriptastfwd_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+class Visitor
+{
+public:
+ Visitor();
+ virtual ~Visitor();
+
+ virtual bool preVisit(Node *) { return true; }
+ virtual void postVisit(Node *) {}
+
+ // Ui
+ virtual bool visit(UiProgram *) { return true; }
+ virtual bool visit(UiImportList *) { return true; }
+ virtual bool visit(UiImport *) { return true; }
+ virtual bool visit(UiPublicMember *) { return true; }
+ virtual bool visit(UiSourceElement *) { return true; }
+ virtual bool visit(UiObjectDefinition *) { return true; }
+ virtual bool visit(UiObjectInitializer *) { return true; }
+ virtual bool visit(UiObjectBinding *) { return true; }
+ virtual bool visit(UiScriptBinding *) { return true; }
+ virtual bool visit(UiArrayBinding *) { return true; }
+ virtual bool visit(UiObjectMemberList *) { return true; }
+ virtual bool visit(UiQualifiedId *) { return true; }
+
+ virtual void endVisit(UiProgram *) {}
+ virtual void endVisit(UiImportList *) {}
+ virtual void endVisit(UiImport *) {}
+ virtual void endVisit(UiPublicMember *) {}
+ virtual void endVisit(UiSourceElement *) {}
+ virtual void endVisit(UiObjectDefinition *) {}
+ virtual void endVisit(UiObjectInitializer *) {}
+ virtual void endVisit(UiObjectBinding *) {}
+ virtual void endVisit(UiScriptBinding *) {}
+ virtual void endVisit(UiArrayBinding *) {}
+ virtual void endVisit(UiObjectMemberList *) {}
+ virtual void endVisit(UiQualifiedId *) {}
+
+ // JavaScript
+ virtual bool visit(ThisExpression *) { return true; }
+ virtual void endVisit(ThisExpression *) {}
+
+ virtual bool visit(IdentifierExpression *) { return true; }
+ virtual void endVisit(IdentifierExpression *) {}
+
+ virtual bool visit(NullExpression *) { return true; }
+ virtual void endVisit(NullExpression *) {}
+
+ virtual bool visit(TrueLiteral *) { return true; }
+ virtual void endVisit(TrueLiteral *) {}
+
+ virtual bool visit(FalseLiteral *) { return true; }
+ virtual void endVisit(FalseLiteral *) {}
+
+ virtual bool visit(StringLiteral *) { return true; }
+ virtual void endVisit(StringLiteral *) {}
+
+ virtual bool visit(NumericLiteral *) { return true; }
+ virtual void endVisit(NumericLiteral *) {}
+
+ virtual bool visit(RegExpLiteral *) { return true; }
+ virtual void endVisit(RegExpLiteral *) {}
+
+ virtual bool visit(ArrayLiteral *) { return true; }
+ virtual void endVisit(ArrayLiteral *) {}
+
+ virtual bool visit(ObjectLiteral *) { return true; }
+ virtual void endVisit(ObjectLiteral *) {}
+
+ virtual bool visit(ElementList *) { return true; }
+ virtual void endVisit(ElementList *) {}
+
+ virtual bool visit(Elision *) { return true; }
+ virtual void endVisit(Elision *) {}
+
+ virtual bool visit(PropertyNameAndValueList *) { return true; }
+ virtual void endVisit(PropertyNameAndValueList *) {}
+
+ virtual bool visit(NestedExpression *) { return true; }
+ virtual void endVisit(NestedExpression *) {}
+
+ virtual bool visit(IdentifierPropertyName *) { return true; }
+ virtual void endVisit(IdentifierPropertyName *) {}
+
+ virtual bool visit(StringLiteralPropertyName *) { return true; }
+ virtual void endVisit(StringLiteralPropertyName *) {}
+
+ virtual bool visit(NumericLiteralPropertyName *) { return true; }
+ virtual void endVisit(NumericLiteralPropertyName *) {}
+
+ virtual bool visit(ArrayMemberExpression *) { return true; }
+ virtual void endVisit(ArrayMemberExpression *) {}
+
+ virtual bool visit(FieldMemberExpression *) { return true; }
+ virtual void endVisit(FieldMemberExpression *) {}
+
+ virtual bool visit(NewMemberExpression *) { return true; }
+ virtual void endVisit(NewMemberExpression *) {}
+
+ virtual bool visit(NewExpression *) { return true; }
+ virtual void endVisit(NewExpression *) {}
+
+ virtual bool visit(CallExpression *) { return true; }
+ virtual void endVisit(CallExpression *) {}
+
+ virtual bool visit(ArgumentList *) { return true; }
+ virtual void endVisit(ArgumentList *) {}
+
+ virtual bool visit(PostIncrementExpression *) { return true; }
+ virtual void endVisit(PostIncrementExpression *) {}
+
+ virtual bool visit(PostDecrementExpression *) { return true; }
+ virtual void endVisit(PostDecrementExpression *) {}
+
+ virtual bool visit(DeleteExpression *) { return true; }
+ virtual void endVisit(DeleteExpression *) {}
+
+ virtual bool visit(VoidExpression *) { return true; }
+ virtual void endVisit(VoidExpression *) {}
+
+ virtual bool visit(TypeOfExpression *) { return true; }
+ virtual void endVisit(TypeOfExpression *) {}
+
+ virtual bool visit(PreIncrementExpression *) { return true; }
+ virtual void endVisit(PreIncrementExpression *) {}
+
+ virtual bool visit(PreDecrementExpression *) { return true; }
+ virtual void endVisit(PreDecrementExpression *) {}
+
+ virtual bool visit(UnaryPlusExpression *) { return true; }
+ virtual void endVisit(UnaryPlusExpression *) {}
+
+ virtual bool visit(UnaryMinusExpression *) { return true; }
+ virtual void endVisit(UnaryMinusExpression *) {}
+
+ virtual bool visit(TildeExpression *) { return true; }
+ virtual void endVisit(TildeExpression *) {}
+
+ virtual bool visit(NotExpression *) { return true; }
+ virtual void endVisit(NotExpression *) {}
+
+ virtual bool visit(BinaryExpression *) { return true; }
+ virtual void endVisit(BinaryExpression *) {}
+
+ virtual bool visit(ConditionalExpression *) { return true; }
+ virtual void endVisit(ConditionalExpression *) {}
+
+ virtual bool visit(Expression *) { return true; }
+ virtual void endVisit(Expression *) {}
+
+ virtual bool visit(Block *) { return true; }
+ virtual void endVisit(Block *) {}
+
+ virtual bool visit(StatementList *) { return true; }
+ virtual void endVisit(StatementList *) {}
+
+ virtual bool visit(VariableStatement *) { return true; }
+ virtual void endVisit(VariableStatement *) {}
+
+ virtual bool visit(VariableDeclarationList *) { return true; }
+ virtual void endVisit(VariableDeclarationList *) {}
+
+ virtual bool visit(VariableDeclaration *) { return true; }
+ virtual void endVisit(VariableDeclaration *) {}
+
+ virtual bool visit(EmptyStatement *) { return true; }
+ virtual void endVisit(EmptyStatement *) {}
+
+ virtual bool visit(ExpressionStatement *) { return true; }
+ virtual void endVisit(ExpressionStatement *) {}
+
+ virtual bool visit(IfStatement *) { return true; }
+ virtual void endVisit(IfStatement *) {}
+
+ virtual bool visit(DoWhileStatement *) { return true; }
+ virtual void endVisit(DoWhileStatement *) {}
+
+ virtual bool visit(WhileStatement *) { return true; }
+ virtual void endVisit(WhileStatement *) {}
+
+ virtual bool visit(ForStatement *) { return true; }
+ virtual void endVisit(ForStatement *) {}
+
+ virtual bool visit(LocalForStatement *) { return true; }
+ virtual void endVisit(LocalForStatement *) {}
+
+ virtual bool visit(ForEachStatement *) { return true; }
+ virtual void endVisit(ForEachStatement *) {}
+
+ virtual bool visit(LocalForEachStatement *) { return true; }
+ virtual void endVisit(LocalForEachStatement *) {}
+
+ virtual bool visit(ContinueStatement *) { return true; }
+ virtual void endVisit(ContinueStatement *) {}
+
+ virtual bool visit(BreakStatement *) { return true; }
+ virtual void endVisit(BreakStatement *) {}
+
+ virtual bool visit(ReturnStatement *) { return true; }
+ virtual void endVisit(ReturnStatement *) {}
+
+ virtual bool visit(WithStatement *) { return true; }
+ virtual void endVisit(WithStatement *) {}
+
+ virtual bool visit(SwitchStatement *) { return true; }
+ virtual void endVisit(SwitchStatement *) {}
+
+ virtual bool visit(CaseBlock *) { return true; }
+ virtual void endVisit(CaseBlock *) {}
+
+ virtual bool visit(CaseClauses *) { return true; }
+ virtual void endVisit(CaseClauses *) {}
+
+ virtual bool visit(CaseClause *) { return true; }
+ virtual void endVisit(CaseClause *) {}
+
+ virtual bool visit(DefaultClause *) { return true; }
+ virtual void endVisit(DefaultClause *) {}
+
+ virtual bool visit(LabelledStatement *) { return true; }
+ virtual void endVisit(LabelledStatement *) {}
+
+ virtual bool visit(ThrowStatement *) { return true; }
+ virtual void endVisit(ThrowStatement *) {}
+
+ virtual bool visit(TryStatement *) { return true; }
+ virtual void endVisit(TryStatement *) {}
+
+ virtual bool visit(Catch *) { return true; }
+ virtual void endVisit(Catch *) {}
+
+ virtual bool visit(Finally *) { return true; }
+ virtual void endVisit(Finally *) {}
+
+ virtual bool visit(FunctionDeclaration *) { return true; }
+ virtual void endVisit(FunctionDeclaration *) {}
+
+ virtual bool visit(FunctionExpression *) { return true; }
+ virtual void endVisit(FunctionExpression *) {}
+
+ virtual bool visit(FormalParameterList *) { return true; }
+ virtual void endVisit(FormalParameterList *) {}
+
+ virtual bool visit(FunctionBody *) { return true; }
+ virtual void endVisit(FunctionBody *) {}
+
+ virtual bool visit(Program *) { return true; }
+ virtual void endVisit(Program *) {}
+
+ virtual bool visit(SourceElements *) { return true; }
+ virtual void endVisit(SourceElements *) {}
+
+ virtual bool visit(FunctionSourceElement *) { return true; }
+ virtual void endVisit(FunctionSourceElement *) {}
+
+ virtual bool visit(StatementSourceElement *) { return true; }
+ virtual void endVisit(StatementSourceElement *) {}
+
+ virtual bool visit(DebuggerStatement *) { return true; }
+ virtual void endVisit(DebuggerStatement *) {}
+};
+
+} } // namespace AST
+
+QT_END_NAMESPACE
+
+#endif // JAVASCRIPTASTVISITOR_P_H
diff --git a/src/declarative/qml/parser/javascriptengine_p.cpp b/src/declarative/qml/parser/javascriptengine_p.cpp
new file mode 100644
index 0000000..d893a90
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptengine_p.cpp
@@ -0,0 +1,191 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "javascriptengine_p.h"
+#include "javascriptnodepool_p.h"
+#include <qnumeric.h>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+uint qHash(const JavaScript::NameId &id)
+{ return qHash(id.asString()); }
+
+QString numberToString(double value)
+{ return QString::number(value); }
+
+int Ecma::RegExp::flagFromChar(const QChar &ch)
+{
+ static QHash<QChar, int> flagsHash;
+ if (flagsHash.isEmpty()) {
+ flagsHash[QLatin1Char('g')] = Global;
+ flagsHash[QLatin1Char('i')] = IgnoreCase;
+ flagsHash[QLatin1Char('m')] = Multiline;
+ }
+ QHash<QChar, int>::const_iterator it;
+ it = flagsHash.constFind(ch);
+ if (it == flagsHash.constEnd())
+ return 0;
+ return it.value();
+}
+
+QString Ecma::RegExp::flagsToString(int flags)
+{
+ QString result;
+ if (flags & Global)
+ result += QLatin1Char('g');
+ if (flags & IgnoreCase)
+ result += QLatin1Char('i');
+ if (flags & Multiline)
+ result += QLatin1Char('m');
+ return result;
+}
+
+NodePool::NodePool(const QString &fileName, Engine *engine)
+ : m_fileName(fileName), m_engine(engine)
+{
+ m_engine->setNodePool(this);
+}
+
+NodePool::~NodePool()
+{
+}
+
+Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &)
+{
+ Q_ASSERT(0);
+ return 0;
+}
+
+static int toDigit(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'a') && (c <= 'z'))
+ return 10 + c - 'a';
+ else if ((c >= 'A') && (c <= 'Z'))
+ return 10 + c - 'A';
+ return -1;
+}
+
+double integerFromString(const char *buf, int size, int radix)
+{
+ if (size == 0)
+ return qSNaN();
+
+ double sign = 1.0;
+ int i = 0;
+ if (buf[0] == '+') {
+ ++i;
+ } else if (buf[0] == '-') {
+ sign = -1.0;
+ ++i;
+ }
+
+ if (((size-i) >= 2) && (buf[i] == '0')) {
+ if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ && (radix < 34)) {
+ if ((radix != 0) && (radix != 16))
+ return 0;
+ radix = 16;
+ i += 2;
+ } else {
+ if (radix == 0) {
+ radix = 8;
+ ++i;
+ }
+ }
+ } else if (radix == 0) {
+ radix = 10;
+ }
+
+ int j = i;
+ for ( ; i < size; ++i) {
+ int d = toDigit(buf[i]);
+ if ((d == -1) || (d >= radix))
+ break;
+ }
+ double result;
+ if (j == i) {
+ if (!qstrcmp(buf, "Infinity"))
+ result = qInf();
+ else
+ result = qSNaN();
+ } else {
+ result = 0;
+ double multiplier = 1;
+ for (--i ; i >= j; --i, multiplier *= radix)
+ result += toDigit(buf[i]) * multiplier;
+ }
+ result *= sign;
+ return result;
+}
+
+double integerFromString(const QString &str, int radix)
+{
+ QByteArray ba = str.trimmed().toUtf8();
+ return integerFromString(ba.constData(), ba.size(), radix);
+}
+
+
+Engine::Engine()
+ : _lexer(0), _nodePool(0)
+{ }
+
+Engine::~Engine()
+{ }
+
+QSet<NameId> Engine::literals() const
+{ return _literals; }
+
+NameId *Engine::intern(const QChar *u, int s)
+{ return const_cast<NameId *>(&*_literals.insert(NameId(u, s))); }
+
+QString Engine::toString(NameId *id)
+{ return id->asString(); }
+
+Lexer *Engine::lexer() const
+{ return _lexer; }
+
+void Engine::setLexer(Lexer *lexer)
+{ _lexer = lexer; }
+
+NodePool *Engine::nodePool() const
+{ return _nodePool; }
+
+void Engine::setNodePool(NodePool *nodePool)
+{ _nodePool = nodePool; }
+
+
+
+} // end of namespace JavaScript
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/parser/javascriptengine_p.h b/src/declarative/qml/parser/javascriptengine_p.h
new file mode 100644
index 0000000..3bd924a
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptengine_p.h
@@ -0,0 +1,145 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#ifndef JAVASCRIPTENGINE_P_H
+#define JAVASCRIPTENGINE_P_H
+
+#include <QString>
+#include <QSet>
+
+#include "javascriptastfwd_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+class NameId
+{
+ QString _text;
+
+public:
+ NameId(const QChar *u, int s)
+ : _text(u, s)
+ { }
+
+ const QString asString() const
+ { return _text; }
+
+ bool operator == (const NameId &other) const
+ { return _text == other._text; }
+
+ bool operator != (const NameId &other) const
+ { return _text != other._text; }
+
+ bool operator < (const NameId &other) const
+ { return _text < other._text; }
+};
+
+uint qHash(const JavaScript::NameId &id);
+
+} // end of namespace JavaScript
+
+#if defined(Q_CC_MSVC) && _MSC_VER <= 1300
+//this ensures that code outside JavaScript can use the hash function
+//it also a workaround for some compilers
+inline uint qHash(const JavaScript::NameId &nameId) { return JavaScript::qHash(nameId); }
+#endif
+
+namespace JavaScript {
+
+class Lexer;
+class NodePool;
+
+namespace Ecma {
+
+class RegExp
+{
+public:
+ enum RegExpFlag {
+ Global = 0x01,
+ IgnoreCase = 0x02,
+ Multiline = 0x04
+ };
+
+public:
+ static int flagFromChar(const QChar &);
+ static QString flagsToString(int flags);
+};
+
+} // end of namespace Ecma
+
+class DiagnosticMessage
+{
+public:
+ enum Kind { Warning, Error };
+
+ DiagnosticMessage()
+ : kind(Error) {}
+
+ DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message)
+ : kind(kind), loc(loc), message(message) {}
+
+ bool isWarning() const
+ { return kind == Warning; }
+
+ bool isError() const
+ { return kind == Error; }
+
+ Kind kind;
+ AST::SourceLocation loc;
+ QString message;
+};
+
+class Engine
+{
+ Lexer *_lexer;
+ NodePool *_nodePool;
+ QSet<NameId> _literals;
+
+public:
+ Engine();
+ ~Engine();
+
+ QSet<NameId> literals() const;
+
+ NameId *intern(const QChar *u, int s);
+
+ static QString toString(NameId *id);
+
+ Lexer *lexer() const;
+ void setLexer(Lexer *lexer);
+
+ NodePool *nodePool() const;
+ void setNodePool(NodePool *nodePool);
+};
+
+} // end of namespace JavaScript
+
+QT_END_NAMESPACE
+
+#endif // JAVASCRIPTENGINE_P_H
diff --git a/src/declarative/qml/parser/javascriptgrammar.cpp b/src/declarative/qml/parser/javascriptgrammar.cpp
new file mode 100644
index 0000000..a879bfe
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptgrammar.cpp
@@ -0,0 +1,829 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptgrammar_p.h"
+
+const char *const JavaScriptGrammar::spell [] = {
+ "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue",
+ "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
+ "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
+ "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
+ "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
+ "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
+ ")", ";", 0, "*", "*=", "string literal", "property", "signal", "switch", "this",
+ "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=",
+ "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "public", "import", 0,
+ 0};
+
+const int JavaScriptGrammar::lhs [] = {
+ 91, 92, 92, 95, 95, 96, 96, 94, 93, 98,
+ 98, 100, 100, 101, 101, 97, 99, 99, 103, 104,
+ 104, 99, 99, 99, 99, 99, 99, 99, 111, 111,
+ 111, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 102, 102, 114, 114, 114, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 102, 102, 117, 117, 117, 117,
+ 116, 116, 119, 119, 121, 121, 121, 121, 121, 121,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 123, 123, 124, 124, 124, 124, 124, 127, 127,
+ 128, 128, 128, 128, 126, 126, 129, 129, 130, 130,
+ 131, 131, 131, 132, 132, 132, 132, 132, 132, 132,
+ 132, 132, 132, 133, 133, 133, 133, 134, 134, 134,
+ 135, 135, 135, 135, 136, 136, 136, 136, 136, 136,
+ 136, 137, 137, 137, 137, 137, 137, 138, 138, 138,
+ 138, 138, 139, 139, 139, 139, 139, 140, 140, 141,
+ 141, 142, 142, 143, 143, 144, 144, 145, 145, 146,
+ 146, 147, 147, 148, 148, 149, 149, 150, 150, 151,
+ 151, 120, 120, 152, 152, 153, 153, 153, 153, 153,
+ 153, 153, 153, 153, 153, 153, 153, 105, 105, 154,
+ 154, 155, 155, 156, 156, 157, 157, 157, 157, 157,
+ 157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
+ 106, 168, 168, 167, 167, 113, 113, 169, 169, 170,
+ 170, 172, 172, 171, 173, 176, 174, 174, 177, 175,
+ 175, 107, 108, 108, 110, 110, 158, 158, 158, 158,
+ 158, 158, 158, 159, 159, 159, 159, 160, 160, 160,
+ 160, 161, 161, 162, 164, 178, 178, 181, 181, 179,
+ 179, 182, 180, 163, 163, 163, 165, 165, 166, 166,
+ 166, 183, 184, 109, 109, 112, 125, 188, 188, 185,
+ 185, 186, 186, 189, 190, 190, 191, 191, 187, 187,
+ 118, 118, 192};
+
+const int JavaScriptGrammar:: rhs[] = {
+ 2, 1, 1, 1, 2, 3, 3, 0, 1, 1,
+ 2, 1, 3, 2, 3, 2, 1, 5, 1, 2,
+ 2, 4, 3, 3, 3, 3, 3, 3, 1, 1,
+ 1, 2, 4, 4, 5, 5, 6, 6, 7, 7,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 3, 3, 4,
+ 5, 3, 4, 3, 1, 3, 1, 2, 3, 4,
+ 1, 2, 3, 5, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 4, 3, 5, 1, 2,
+ 4, 4, 4, 3, 0, 1, 1, 3, 1, 1,
+ 1, 2, 2, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 3, 3, 3, 1, 3, 3,
+ 1, 3, 3, 3, 1, 3, 3, 3, 3, 3,
+ 3, 1, 3, 3, 3, 3, 3, 1, 3, 3,
+ 3, 3, 1, 3, 3, 3, 3, 1, 3, 1,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 1, 3, 1, 3, 1, 3, 1, 5, 1,
+ 5, 1, 3, 1, 3, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 0,
+ 1, 1, 3, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 1, 2, 0, 1, 3, 3, 1, 1, 1,
+ 3, 1, 3, 2, 2, 2, 0, 1, 2, 0,
+ 1, 1, 2, 2, 7, 5, 7, 7, 5, 9,
+ 10, 7, 8, 2, 2, 3, 3, 2, 2, 3,
+ 3, 3, 3, 5, 5, 3, 5, 1, 2, 0,
+ 1, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 5, 2, 2, 2, 8, 8, 1, 3, 0,
+ 1, 0, 1, 1, 1, 2, 1, 1, 0, 1,
+ 0, 1, 2};
+
+const int JavaScriptGrammar::action_default [] = {
+ 8, 2, 0, 4, 3, 0, 0, 0, 6, 7,
+ 5, 65, 45, 46, 43, 44, 47, 9, 0, 1,
+ 0, 0, 16, 66, 41, 248, 0, 0, 46, 14,
+ 47, 249, 17, 10, 0, 0, 0, 42, 0, 31,
+ 30, 29, 0, 0, 35, 0, 36, 151, 218, 182,
+ 190, 186, 130, 202, 178, 0, 115, 49, 131, 194,
+ 198, 119, 148, 129, 134, 114, 168, 155, 0, 55,
+ 56, 52, 319, 321, 0, 0, 0, 0, 0, 0,
+ 50, 53, 0, 0, 54, 48, 0, 51, 0, 0,
+ 144, 0, 0, 131, 150, 133, 132, 0, 0, 0,
+ 146, 147, 145, 149, 0, 179, 0, 0, 0, 0,
+ 169, 0, 0, 0, 0, 0, 0, 159, 0, 0,
+ 0, 153, 154, 152, 157, 161, 160, 158, 156, 171,
+ 170, 172, 0, 187, 0, 183, 0, 0, 125, 112,
+ 124, 113, 81, 82, 83, 108, 84, 109, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 110, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 111, 0, 0, 123, 219, 126, 0, 127,
+ 0, 128, 122, 39, 40, 0, 215, 208, 206, 213,
+ 214, 212, 211, 217, 210, 209, 207, 216, 203, 0,
+ 191, 0, 0, 195, 0, 0, 199, 0, 0, 125,
+ 117, 0, 116, 0, 121, 135, 0, 320, 310, 311,
+ 0, 308, 0, 309, 0, 312, 226, 233, 232, 240,
+ 228, 0, 229, 313, 0, 318, 230, 231, 236, 234,
+ 315, 314, 317, 237, 0, 0, 0, 0, 0, 319,
+ 45, 0, 321, 46, 220, 262, 47, 0, 0, 0,
+ 0, 0, 238, 239, 227, 235, 263, 264, 307, 316,
+ 0, 278, 279, 280, 281, 0, 274, 275, 276, 277,
+ 304, 305, 0, 0, 0, 0, 0, 267, 268, 224,
+ 222, 184, 192, 188, 204, 180, 225, 0, 131, 196,
+ 200, 173, 162, 0, 0, 181, 0, 0, 0, 0,
+ 174, 0, 0, 0, 0, 0, 166, 164, 167, 165,
+ 163, 176, 175, 177, 0, 189, 0, 185, 0, 223,
+ 131, 0, 205, 220, 221, 0, 220, 0, 0, 270,
+ 0, 0, 0, 272, 0, 193, 0, 0, 197, 0,
+ 0, 201, 260, 0, 252, 261, 255, 0, 259, 0,
+ 220, 253, 0, 220, 0, 0, 271, 0, 0, 0,
+ 273, 320, 310, 0, 0, 312, 0, 306, 0, 296,
+ 0, 0, 0, 266, 0, 265, 0, 322, 0, 80,
+ 242, 245, 0, 81, 248, 84, 109, 86, 87, 52,
+ 91, 92, 45, 93, 96, 50, 53, 46, 220, 47,
+ 54, 99, 48, 101, 51, 103, 104, 249, 106, 107,
+ 111, 0, 73, 0, 0, 75, 79, 77, 63, 76,
+ 78, 0, 74, 62, 243, 241, 119, 120, 125, 0,
+ 118, 0, 295, 0, 282, 283, 0, 294, 0, 0,
+ 0, 285, 290, 288, 291, 0, 0, 289, 290, 0,
+ 286, 0, 287, 244, 293, 0, 244, 292, 0, 297,
+ 298, 0, 244, 299, 300, 0, 0, 301, 0, 0,
+ 0, 302, 303, 137, 136, 0, 0, 0, 269, 0,
+ 0, 0, 284, 67, 0, 0, 71, 57, 0, 59,
+ 69, 0, 60, 70, 72, 61, 68, 58, 0, 64,
+ 141, 139, 143, 140, 138, 142, 0, 0, 0, 33,
+ 0, 34, 0, 37, 38, 32, 15, 11, 0, 23,
+ 26, 24, 0, 25, 28, 244, 0, 19, 0, 27,
+ 22, 81, 248, 84, 109, 86, 87, 52, 91, 92,
+ 45, 93, 96, 50, 53, 46, 220, 47, 54, 99,
+ 48, 101, 51, 103, 104, 249, 106, 107, 111, 49,
+ 0, 12, 0, 18, 13, 20, 21, 257, 250, 0,
+ 258, 254, 0, 256, 246, 0, 247, 251, 323};
+
+const int JavaScriptGrammar::goto_default [] = {
+ 6, 5, 19, 1, 4, 3, 32, 34, 33, 570,
+ 22, 18, 538, 539, 231, 226, 230, 232, 229, 236,
+ 517, 235, 264, 57, 65, 495, 494, 388, 387, 48,
+ 386, 389, 140, 61, 56, 178, 63, 52, 177, 58,
+ 64, 90, 62, 47, 67, 66, 301, 54, 295, 49,
+ 291, 51, 293, 50, 292, 59, 299, 60, 300, 53,
+ 294, 290, 331, 443, 296, 297, 390, 237, 228, 227,
+ 239, 265, 238, 243, 262, 263, 392, 391, 36, 579,
+ 578, 353, 354, 581, 356, 580, 355, 451, 455, 458,
+ 454, 453, 473, 474, 220, 234, 216, 219, 233, 241,
+ 240, 0};
+
+const int JavaScriptGrammar::action_index [] = {
+ 8, -91, 14, -91, -15, 296, 67, 94, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, 109, -91,
+ 184, 408, -91, -91, -91, -91, 45, 125, 170, -91,
+ 46, -91, -91, -91, 429, 171, 130, -91, 120, -91,
+ -91, -91, -19, 169, -91, 733, -91, 72, -91, 22,
+ -26, -59, 173, -91, 278, 174, -91, -91, 574, 51,
+ 112, 183, 177, -91, -91, -91, 412, 214, 733, -91,
+ -91, -91, 161, 1566, 980, 733, 733, 733, 653, 733,
+ -91, -91, 733, 733, -91, -91, 733, -91, 733, 733,
+ -91, 733, 733, 98, 235, -91, -91, 733, 733, 733,
+ -91, -91, -91, 230, 733, 276, 733, 733, 733, 733,
+ 396, 733, 733, 733, 733, 733, 733, 288, 733, 733,
+ 733, 88, 87, 74, 288, 288, 288, 218, 221, 486,
+ 372, 362, 733, 4, 733, 76, 1479, 733, 733, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, 102, 733, -91, -91, 60, 3, -91,
+ 733, -91, -91, -91, -91, 733, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, 733,
+ -6, 733, 733, 30, 32, 733, -91, 1479, 733, 733,
+ -91, 107, -91, -14, -91, -91, 69, -91, 191, 49,
+ 18, -91, 233, -91, 47, 1827, -91, -91, -91, -91,
+ -91, 204, -91, -91, 39, -91, -91, -91, -91, -91,
+ -91, 1827, -91, -91, 322, 281, 103, 1740, 50, 203,
+ 77, 40, 2001, 53, 733, -91, 52, 29, 733, 25,
+ 28, 35, -91, -91, -91, -91, -91, -91, -91, -91,
+ 113, -91, -91, -91, -91, 106, -91, -91, -91, -91,
+ -91, -91, 15, 68, 733, 135, 119, -91, -91, 897,
+ -91, 82, 58, 17, -91, 261, 84, 42, 494, 91,
+ 79, 304, 288, 208, 733, 245, 733, 733, 733, 733,
+ 418, 733, 733, 733, 733, 733, 288, 288, 288, 288,
+ 288, 343, 336, 279, 733, -57, 733, 19, 733, -91,
+ 574, 733, -91, 733, -7, -30, 733, -60, 1740, -91,
+ 733, 111, 1740, -91, 733, 2, 733, 733, 43, 37,
+ 733, -91, 34, 118, 23, -91, -91, 733, -91, 238,
+ 733, -91, -5, 733, -17, 1740, -91, 733, 133, 1740,
+ -91, -9, 194, -32, -8, 1827, -25, -91, 1740, -91,
+ 733, 100, 1740, 21, 1740, -91, 31, 26, -20, -91,
+ -91, 1740, -38, 283, 41, 291, 85, 733, 1740, -1,
+ -34, 252, 54, -27, 653, 9, 5, -91, 817, -91,
+ 6, -21, 7, 733, 11, -28, 733, 1, 733, -33,
+ -10, 733, -91, 1653, 33, -91, -91, -91, -91, -91,
+ -91, 733, -91, -91, -91, -91, 172, -91, 733, -24,
+ -91, 1740, -91, 73, -91, -91, 1740, -91, 733, 93,
+ 0, -91, 24, -91, 36, 122, 733, -91, 44, 48,
+ -91, -3, -91, 1740, -91, 110, 1740, -91, 192, -91,
+ -91, 124, 1740, 27, -91, -12, -29, -91, 155, -53,
+ -22, -91, -91, -91, -91, 733, 123, 1740, -91, 733,
+ 92, 1740, -91, -91, 105, 1229, -91, -91, 1146, -91,
+ -91, 1063, -91, -91, -91, -91, -91, -91, 90, -91,
+ -91, -91, -91, -91, -91, -91, 71, 70, 222, -91,
+ 733, -91, 164, -91, -91, -91, -91, -91, 1392, -91,
+ -91, -91, 268, -91, -91, 1914, 1312, -91, 75, -91,
+ -91, 350, 55, 303, 108, 733, 1740, 59, 38, 242,
+ 62, 40, 527, 63, 81, -91, 817, -91, 138, 29,
+ 65, 733, 78, 56, 733, 80, 733, 61, 66, 57,
+ 101, -91, 347, -91, -91, -91, -91, 64, -91, 140,
+ -91, -91, 733, -91, -91, 144, -91, -91, -91,
+
+ -102, -102, -102, -102, 19, 103, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -4, 249, -102, -102, -102, -102, -102, -7, -102, -102,
+ -102, -102, -102, -102, 257, -102, -13, -102, -11, -102,
+ -102, -102, -102, -102, -102, -3, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -44, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, 141, -102,
+ -102, -102, -8, -102, 0, 16, 116, 122, 129, 119,
+ -102, -102, 90, 64, -102, -102, 94, -102, 91, 86,
+ -102, 71, 79, -102, -102, -102, -102, 159, 81, 76,
+ -102, -102, -102, -102, 98, -102, 67, 63, 47, 163,
+ -102, 160, 115, 104, 105, 127, 133, -102, 151, 144,
+ 130, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, 145, -102, 152, -102, 162, 31, 21, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, 23, -102, -102, -102, -102, -102,
+ 29, -102, -102, -102, -102, 34, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, 89,
+ -102, 68, 36, -102, -102, 42, -102, 235, 46, 49,
+ -102, -102, -102, -102, -102, -102, -102, -102, 33, -102,
+ -102, -102, 26, -102, -102, -18, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, 53, -102, -102, 8, 20, -102, -5, -102, 32,
+ -102, -102, -102, -102, 39, -102, -102, -102, 37, 73,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, 40, -102, -102, -102, -102, 97,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, 41, 213, -102, 186, 199, 203, 209,
+ -102, 50, 51, 38, 57, 60, -102, -102, -102, -102,
+ -102, -102, -102, -102, 212, -102, 174, -102, 166, -102,
+ -102, 168, -102, 125, -102, -102, 61, -102, 1, -102,
+ 45, -102, -9, -102, 172, -102, 184, 176, -102, -102,
+ 170, -102, -102, -102, -102, -102, -102, 215, -102, 124,
+ 132, -102, -102, 178, -102, -29, -102, 25, -102, 2,
+ -102, -102, 62, -102, -102, 102, -102, -102, -28, -102,
+ 22, -102, -31, -102, -33, -102, -102, -102, -102, -102,
+ -102, -34, -102, 17, -102, 18, -102, 111, -20, -102,
+ -102, 24, -102, -102, 153, -102, -102, -102, 30, -102,
+ -102, -102, -102, 28, -102, 73, 140, -102, 205, -102,
+ -102, 5, -102, 44, -102, -102, -102, -102, -102, -102,
+ -102, 43, -102, -102, -102, -102, -102, -102, 135, -102,
+ -102, 7, -102, -102, -102, -102, 4, -102, 55, -102,
+ -102, -102, -102, -102, -25, -102, 48, -102, 9, -102,
+ -102, -102, -102, -69, -102, -102, -70, -102, -102, -102,
+ -102, -102, -102, -92, -102, -102, -12, -102, -10, -102,
+ -1, -102, -102, -102, -102, 11, -102, -40, -102, 14,
+ -102, -39, -102, -102, -102, -17, -102, -102, 54, -102,
+ -102, -24, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ 3, -102, -102, -102, -102, -102, -102, -102, 267, -102,
+ -102, -102, 12, -102, -102, -102, 301, -102, -102, -102,
+ -102, -19, -102, -15, -102, 59, -64, -102, -102, -2,
+ -102, -102, 142, -102, -102, -102, -14, -102, -102, -102,
+ -102, 6, -102, 73, 52, -102, 75, -102, -102, -102,
+ -102, -102, 128, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -6, -102, -102, 58, -102, -102, -102};
+
+const int JavaScriptGrammar::action_info [] = {
+ 338, 174, 289, 485, 472, 472, -89, 480, -105, 380,
+ 43, 472, -79, -78, -100, 448, -97, 435, -102, 134,
+ 304, 326, 132, 104, 478, 375, 489, 372, 374, 456,
+ 377, 336, 199, 452, 423, 433, 440, 384, 421, 205,
+ 431, 456, 132, 365, 350, 344, 214, 476, -108, 456,
+ 324, 357, 462, 199, 367, 463, 363, 222, 472, 446,
+ 441, -75, -108, 182, 485, 448, -89, 588, 180, -75,
+ -97, 489, -100, 2, 289, 525, 380, 104, 224, 7,
+ 225, 582, 134, 304, 378, -102, 289, -105, -79, 472,
+ -65, 283, 328, 344, 268, 326, 2, 485, 174, 518,
+ 174, 174, 489, 333, 284, 218, 324, 372, 174, 572,
+ 174, 38, 91, 498, 91, 174, 0, 466, 174, 174,
+ 0, 0, 0, 92, 20, 92, 359, 91, 91, 346,
+ 475, 174, 459, 347, 445, 444, 576, 575, 92, 92,
+ 95, 174, 21, 174, 476, -78, 281, 280, 585, 39,
+ 509, 96, 491, 450, 12, 9, 8, 573, 175, 12,
+ 382, 499, 201, 212, 281, 280, 202, 279, 278, 281,
+ 280, 342, 174, 12, 274, 273, 45, 460, 528, 360,
+ 288, 287, 174, 487, 12, 0, 20, 207, 136, 97,
+ 12, 13, 16, 369, 41, 286, 13, 16, 207, 39,
+ 174, 586, 584, 0, 21, 40, 208, 137, 438, 138,
+ 13, 16, 174, 12, 0, 0, 0, 208, 0, 209,
+ 12, 13, 16, 12, 0, 524, 523, 13, 16, 520,
+ 46, 44, 12, 0, 98, 184, 183, 12, 0, 118,
+ 99, 119, 97, 118, 41, 119, 118, 97, 119, 0,
+ 13, 16, 120, 470, 469, 40, 120, 13, 16, 120,
+ 13, 16, 12, 306, 307, 267, 266, 12, 0, 13,
+ 16, 12, 0, 0, 13, 16, 174, 0, -319, 306,
+ 307, 12, 0, 521, 519, 0, 0, 98, -319, 0,
+ 308, 309, 98, 99, 106, 107, 106, 107, 99, 13,
+ 16, 21, 311, 312, 13, 16, 308, 309, 13, 16,
+ 12, 313, 12, 118, 314, 119, 315, 0, 13, 16,
+ 12, 108, 109, 108, 109, 12, 120, 311, 312, 267,
+ 266, 0, 12, 0, 0, 0, 313, 0, 0, 314,
+ 0, 315, 277, 276, 272, 271, 0, 13, 16, 13,
+ 16, 12, 277, 276, 0, 15, 0, 13, 16, 311,
+ 312, 0, 13, 16, 277, 276, 311, 312, 313, 13,
+ 16, 314, 0, 315, 0, 313, 12, 0, 314, 12,
+ 315, 14, 0, 272, 271, 111, 112, 0, 13, 16,
+ 0, 0, 0, 113, 114, 111, 112, 115, 0, 116,
+ 0, 0, 0, 113, 114, 0, 15, 115, 0, 116,
+ 0, 272, 271, 13, 16, 0, 13, 16, 26, 111,
+ 112, 0, 0, 0, 0, 0, 0, 113, 114, 0,
+ 27, 115, 14, 116, 0, 111, 112, 12, 0, 26,
+ 0, 311, 312, 113, 114, 0, 0, 115, 0, 116,
+ 313, 27, 0, 314, 0, 315, 0, 0, 12, 0,
+ 0, 0, 0, 29, 0, 0, 0, 15, 0, 0,
+ 0, 0, 0, 0, 28, 30, 0, 0, 0, 0,
+ 0, 0, 31, 0, 526, 0, 0, 0, 15, 0,
+ 0, 25, 0, 14, 0, 28, 30, 186, 0, 0,
+ 0, 0, 0, 31, 0, 0, 0, 187, 0, 111,
+ 112, 188, 25, 0, 14, 0, 0, 113, 114, 0,
+ 189, 115, 190, 116, 0, 340, 0, 0, 0, 0,
+ 0, 0, 0, 191, 0, 192, 95, 0, 0, 69,
+ 70, 0, 0, 193, 0, 0, 194, 96, 0, 72,
+ 0, 0, 195, 0, 0, 0, 12, 0, 196, 0,
+ 73, 74, 0, 75, 0, 0, 0, 0, 0, 0,
+ 78, 0, 0, 197, 81, 0, 0, 186, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 187, 0, 0,
+ 0, 188, 84, 13, 16, 0, 85, 0, 0, 0,
+ 189, 0, 190, 0, 0, 0, 0, 80, 87, 71,
+ 0, 0, 0, 191, 0, 192, 95, 0, 0, 0,
+ 0, 0, 0, 193, 0, 0, 194, 96, 0, 0,
+ 0, 0, 195, 0, 0, 0, 0, 0, 196, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 197, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 69, 70, 0, 0, 0,
+ 0, 0, 0, 0, 0, 72, 0, 0, 0, 0,
+ 0, 0, 12, 0, 0, 0, 73, 74, 0, 75,
+ 0, 0, 0, 0, 0, 0, 78, 0, 0, 0,
+ 81, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 84, 13,
+ 16, 0, 85, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 80, 87, 71, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 69, 70, 0, 0, 0,
+ 0, 0, 0, 0, 0, 72, 0, 0, 0, 0,
+ 0, 0, 12, 0, 0, 0, 73, 74, 0, 75,
+ 0, 0, 0, 76, 0, 77, 78, 79, 0, 0,
+ 81, 0, 0, 0, 82, 0, 83, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 84, 13,
+ 16, 0, 85, 0, 86, 0, 88, 0, 89, 0,
+ 0, 0, 0, 80, 87, 71, 0, 0, 0, 0,
+ 0, 0, 0, 0, -98, 0, 0, 0, 68, 69,
+ 70, 0, 0, 0, 0, 0, 0, 0, 0, 72,
+ 0, 0, 0, 0, 0, 0, 12, 0, 0, 0,
+ 73, 74, 0, 75, 0, 0, 0, 76, 0, 77,
+ 78, 79, 0, 0, 81, 0, 0, 0, 82, 0,
+ 83, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 84, 13, 16, 0, 85, 0, 86, 0,
+ 88, 0, 89, 0, 0, 0, 0, 80, 87, 71,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 69,
+ 70, 0, 0, 0, 0, 0, 0, 0, 0, 72,
+ 0, 0, 0, 0, 0, 0, 12, 0, 0, 0,
+ 73, 74, 0, 75, 0, 0, 0, 76, 0, 77,
+ 78, 79, 0, 0, 81, 0, 0, 0, 82, 0,
+ 83, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 84, 13, 16, 0, 85, 0, 86, 0,
+ 88, 303, 89, 0, 0, 0, 0, 80, 87, 71,
+ 0, 0, 0, 0, 0, 0, 0, 0, 496, 0,
+ 0, 68, 69, 70, 0, 0, 0, 0, 0, 0,
+ 0, 0, 72, 0, 0, 0, 0, 0, 0, 12,
+ 0, 0, 0, 73, 74, 0, 75, 0, 0, 0,
+ 76, 0, 77, 78, 79, 0, 0, 81, 0, 0,
+ 0, 82, 0, 83, 0, 0, 497, 0, 0, 0,
+ 0, 0, 0, 0, 0, 84, 13, 16, 0, 85,
+ 0, 86, 0, 88, 0, 89, 0, 0, 0, 0,
+ 80, 87, 71, 0, 0, 0, 0, 0, 0, 0,
+ 0, 504, 0, 0, 68, 69, 70, 0, 0, 0,
+ 0, 0, 0, 0, 0, 72, 0, 0, 0, 0,
+ 0, 0, 12, 0, 0, 0, 73, 74, 0, 75,
+ 0, 0, 0, 76, 0, 77, 78, 79, 0, 0,
+ 81, 0, 0, 0, 82, 0, 83, 0, 0, 505,
+ 0, 0, 0, 0, 0, 0, 0, 0, 84, 13,
+ 16, 0, 85, 0, 86, 0, 88, 0, 89, 0,
+ 0, 0, 0, 80, 87, 71, 0, 0, 0, 0,
+ 0, 0, 0, 0, 496, 0, 0, 68, 69, 70,
+ 0, 0, 0, 0, 0, 0, 0, 0, 72, 0,
+ 0, 0, 0, 0, 0, 12, 0, 0, 0, 73,
+ 74, 0, 75, 0, 0, 0, 76, 0, 77, 78,
+ 79, 0, 0, 81, 0, 0, 0, 82, 0, 83,
+ 0, 0, 502, 0, 0, 0, 0, 0, 0, 0,
+ 0, 84, 13, 16, 0, 85, 0, 86, 0, 88,
+ 0, 89, 0, 0, 0, 0, 80, 87, 71, 0,
+ 0, 0, 0, 0, 0, 0, 0, 504, 0, 0,
+ 68, 69, 70, 0, 0, 0, 0, 0, 0, 0,
+ 0, 72, 0, 0, 0, 0, 0, 0, 12, 0,
+ 0, 0, 73, 74, 0, 75, 0, 0, 0, 76,
+ 0, 77, 78, 79, 0, 0, 81, 0, 0, 0,
+ 82, 0, 83, 0, 0, 507, 0, 0, 0, 0,
+ 0, 0, 0, 0, 84, 13, 16, 0, 85, 0,
+ 86, 0, 88, 0, 89, 0, 0, 0, 0, 80,
+ 87, 71, 0, 0, 0, 0, 0, 0, 0, 0,
+ 496, 0, 0, 68, 69, 70, 0, 0, 0, 0,
+ 0, 0, 0, 0, 72, 0, 0, 0, 0, 0,
+ 0, 12, 0, 0, 0, 73, 74, 0, 75, 0,
+ 0, 0, 76, 0, 77, 78, 79, 0, 0, 81,
+ 0, 0, 0, 82, 0, 83, 0, 0, 497, 0,
+ 0, 15, 0, 0, 0, 0, 0, 84, 13, 16,
+ 0, 85, 0, 86, 0, 88, 0, 89, 0, 0,
+ 0, 0, 80, 87, 71, 0, 0, 14, 0, 0,
+ 0, 0, 0, 68, 69, 70, 0, 0, 0, 0,
+ 0, 0, 0, 0, 72, 0, 0, 0, 0, 0,
+ 0, 12, 251, 0, 0, 535, 536, 0, 75, 0,
+ 0, 0, 76, 0, 77, 78, 79, 0, 0, 81,
+ 0, 0, 0, 82, 0, 83, 0, 0, 0, 0,
+ 0, 0, 0, 255, 0, 0, 0, 84, 13, 16,
+ 0, 85, 0, 86, 0, 88, 0, 89, 0, 0,
+ 0, 0, 80, 87, 71, 0, 246, 0, 537, 0,
+ 0, 0, 0, 142, 143, 144, 0, 0, 146, 148,
+ 149, 0, 0, 150, 0, 151, 0, 0, 0, 153,
+ 154, 155, 0, 0, 0, 0, 0, 0, 12, 156,
+ 157, 158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 159, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 162, 0,
+ 0, 0, 0, 0, 0, 13, 16, 163, 164, 165,
+ 0, 167, 168, 169, 170, 171, 172, 0, 0, 160,
+ 166, 152, 145, 147, 161, 0, 0, 0, 0, 0,
+ 142, 143, 144, 0, 0, 146, 148, 149, 0, 0,
+ 150, 0, 151, 0, 0, 0, 153, 154, 155, 0,
+ 0, 0, 0, 0, 0, 425, 156, 157, 158, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 159,
+ 0, 0, 0, 426, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 162, 0, 0, 0, 0,
+ 0, 430, 427, 429, 163, 164, 165, 0, 167, 168,
+ 169, 170, 171, 172, 0, 0, 160, 166, 152, 145,
+ 147, 161, 0, 0, 0, 0, 0, 142, 143, 144,
+ 0, 0, 146, 148, 149, 0, 0, 150, 0, 151,
+ 0, 0, 0, 153, 154, 155, 0, 0, 0, 0,
+ 0, 0, 425, 156, 157, 158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 159, 0, 0, 0,
+ 426, 0, 0, 0, 0, 0, 0, 0, 428, 0,
+ 0, 0, 162, 0, 0, 0, 0, 0, 430, 427,
+ 429, 163, 164, 165, 0, 167, 168, 169, 170, 171,
+ 172, 0, 0, 160, 166, 152, 145, 147, 161, 0,
+ 0, 0, 0, 0, 244, 0, 0, 0, 0, 245,
+ 0, 68, 69, 70, 247, 0, 0, 0, 0, 0,
+ 0, 248, 72, 0, 0, 0, 0, 0, 0, 250,
+ 251, 0, 0, 252, 74, 0, 75, 0, 0, 0,
+ 76, 0, 77, 78, 79, 0, 0, 81, 0, 0,
+ 0, 82, 0, 83, 0, 0, 0, 0, 0, 254,
+ 0, 255, 0, 0, 0, 84, 253, 256, 257, 85,
+ 258, 86, 259, 88, 31, 89, 260, 261, 0, 0,
+ 80, 87, 71, 25, 246, 0, 0, 0, 0, 0,
+ 0, 244, 0, 0, 0, 0, 245, 0, 68, 69,
+ 70, 247, 0, 0, 0, 0, 0, 0, 248, 249,
+ 0, 0, 0, 0, 0, 0, 250, 251, 0, 0,
+ 252, 74, 0, 75, 0, 0, 0, 76, 0, 77,
+ 78, 79, 0, 0, 81, 0, 0, 0, 82, 0,
+ 83, 0, 0, 0, 0, 0, 254, 0, 255, 0,
+ 0, 0, 84, 253, 256, 257, 85, 258, 86, 259,
+ 88, 31, 89, 260, 261, 0, 0, 80, 87, 71,
+ 25, 246, 0, 0, 0, 0, 0, 0, 541, 143,
+ 144, 0, 0, 543, 148, 545, 69, 70, 546, 0,
+ 151, 0, 0, 0, 153, 548, 549, 0, 0, 0,
+ 0, 0, 0, 550, 551, 157, 158, 252, 74, 0,
+ 75, 0, 0, 0, 76, 0, 77, 552, 79, 0,
+ 0, 554, 0, 0, 0, 82, 0, 83, 0, 0,
+ 0, 0, 0, 556, 0, 255, 0, 0, 0, 558,
+ 555, 557, 559, 560, 561, 86, 563, 564, 565, 566,
+ 567, 568, 0, 0, 553, 562, 547, 542, 544, 161,
+ 0, 0, 0, 0, 0, 393, 143, 144, 0, 0,
+ 395, 148, 397, 69, 70, 398, 0, 151, 0, 0,
+ 0, 153, 400, 401, 0, 0, 0, 0, 0, 0,
+ 402, 403, 157, 158, 252, 74, 0, 75, 0, 0,
+ 0, 76, 0, 77, 404, 79, 0, 0, 406, 0,
+ 0, 0, 82, 0, 83, 0, -244, 0, 0, 0,
+ 408, 0, 255, 0, 0, 0, 410, 407, 409, 411,
+ 412, 413, 86, 415, 416, 417, 418, 419, 420, 0,
+ 0, 405, 414, 399, 394, 396, 161, 0, 0, 0,
+ 0, 0,
+
+ 334, 477, 282, 482, 270, 503, 467, 464, 275, 42,
+ 577, 55, 506, 479, 481, 217, 516, 522, 185, 23,
+ 468, 217, 540, 583, 10, 486, 488, 492, 490, 493,
+ 508, 270, 434, 385, 422, 383, 381, 366, 379, 368,
+ 270, 275, 468, 275, 334, 173, 282, 217, 242, 223,
+ 179, 468, 176, 334, 285, 371, 221, 343, 181, 341,
+ 211, 282, 465, 198, 352, 204, 457, 339, 370, 449,
+ 447, 206, 432, 442, 424, 334, 0, 93, 179, 501,
+ 0, 577, 318, 500, 213, 221, 93, 0, 471, 93,
+ 93, 93, 130, 483, 316, 317, 93, 461, 93, 93,
+ 215, 319, 93, 93, 320, 514, 93, 93, 129, 17,
+ 93, 0, 110, 94, 93, 93, 484, 102, 93, 242,
+ 93, 103, 101, 203, 337, 93, 11, 484, 93, 93,
+ 93, 513, 483, 93, 574, 515, 298, 93, 587, 334,
+ 0, 302, 200, 93, 93, 105, 334, 352, 125, 126,
+ 93, 11, 215, 269, 93, 93, 373, 510, 93, 124,
+ 512, 93, 436, 511, 179, 437, 93, 0, 242, 93,
+ 439, 127, 93, 123, 0, 436, 0, 128, 437, 93,
+ 93, 483, 215, 93, 93, 139, 436, 122, 335, 437,
+ 93, 93, 334, 141, 121, 362, 133, 376, 93, 93,
+ 100, 135, 93, 0, 117, 330, 361, 330, 131, 330,
+ 302, 93, 302, 93, 302, 330, 302, 0, 302, 0,
+ 302, 0, 0, 93, 327, 93, 345, 329, 302, 332,
+ 302, 351, 310, 0, 0, 0, 0, 349, 93, 0,
+ 348, 364, 93, 302, 93, 321, 484, 302, 93, 322,
+ 0, 93, 93, 302, 330, 323, 302, 302, 139, 302,
+ 35, 305, 0, 0, 325, 527, 141, 210, 35, 0,
+ 24, 37, 11, 0, 0, 0, 358, 0, 24, 37,
+ 11, 532, 529, 531, 533, 530, 534, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 571, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 569, 0, 0, 0, 0, 0,
+ 493, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
+
+const int JavaScriptGrammar::action_check [] = {
+ 60, 8, 36, 36, 33, 33, 7, 60, 7, 36,
+ 29, 33, 7, 7, 7, 36, 7, 55, 7, 78,
+ 1, 78, 48, 1, 36, 33, 36, 36, 60, 5,
+ 55, 61, 2, 33, 8, 55, 60, 16, 7, 7,
+ 7, 5, 48, 60, 7, 2, 60, 20, 7, 5,
+ 48, 17, 55, 2, 31, 7, 61, 8, 33, 7,
+ 7, 7, 7, 60, 36, 36, 7, 0, 8, 7,
+ 7, 36, 7, 88, 36, 29, 36, 1, 60, 65,
+ 33, 17, 78, 1, 7, 7, 36, 7, 7, 33,
+ 33, 76, 8, 2, 55, 78, 88, 36, 8, 29,
+ 8, 8, 36, 61, 36, 36, 48, 36, 8, 8,
+ 8, 66, 40, 8, 40, 8, -1, 7, 8, 8,
+ -1, -1, -1, 51, 15, 51, 8, 40, 40, 50,
+ 6, 8, 10, 54, 61, 62, 61, 62, 51, 51,
+ 42, 8, 33, 8, 20, 7, 61, 62, 8, 29,
+ 60, 53, 60, 60, 29, 61, 62, 56, 56, 29,
+ 60, 56, 50, 56, 61, 62, 54, 61, 62, 61,
+ 62, 60, 8, 29, 61, 62, 7, 55, 7, 61,
+ 61, 62, 8, 60, 29, -1, 15, 15, 15, 12,
+ 29, 66, 67, 60, 74, 60, 66, 67, 15, 29,
+ 8, 61, 62, -1, 33, 85, 34, 34, 36, 36,
+ 66, 67, 8, 29, -1, -1, -1, 34, -1, 36,
+ 29, 66, 67, 29, -1, 61, 62, 66, 67, 7,
+ 61, 62, 29, -1, 57, 61, 62, 29, -1, 25,
+ 63, 27, 12, 25, 74, 27, 25, 12, 27, -1,
+ 66, 67, 38, 61, 62, 85, 38, 66, 67, 38,
+ 66, 67, 29, 18, 19, 61, 62, 29, -1, 66,
+ 67, 29, -1, -1, 66, 67, 8, -1, 36, 18,
+ 19, 29, -1, 61, 62, -1, -1, 57, 36, -1,
+ 45, 46, 57, 63, 18, 19, 18, 19, 63, 66,
+ 67, 33, 23, 24, 66, 67, 45, 46, 66, 67,
+ 29, 32, 29, 25, 35, 27, 37, -1, 66, 67,
+ 29, 45, 46, 45, 46, 29, 38, 23, 24, 61,
+ 62, -1, 29, -1, -1, -1, 32, -1, -1, 35,
+ -1, 37, 61, 62, 61, 62, -1, 66, 67, 66,
+ 67, 29, 61, 62, -1, 59, -1, 66, 67, 23,
+ 24, -1, 66, 67, 61, 62, 23, 24, 32, 66,
+ 67, 35, -1, 37, -1, 32, 29, -1, 35, 29,
+ 37, 85, -1, 61, 62, 23, 24, -1, 66, 67,
+ -1, -1, -1, 31, 32, 23, 24, 35, -1, 37,
+ -1, -1, -1, 31, 32, -1, 59, 35, -1, 37,
+ -1, 61, 62, 66, 67, -1, 66, 67, 10, 23,
+ 24, -1, -1, -1, -1, -1, -1, 31, 32, -1,
+ 22, 35, 85, 37, -1, 23, 24, 29, -1, 10,
+ -1, 23, 24, 31, 32, -1, -1, 35, -1, 37,
+ 32, 22, -1, 35, -1, 37, -1, -1, 29, -1,
+ -1, -1, -1, 55, -1, -1, -1, 59, -1, -1,
+ -1, -1, -1, -1, 66, 67, -1, -1, -1, -1,
+ -1, -1, 74, -1, 55, -1, -1, -1, 59, -1,
+ -1, 83, -1, 85, -1, 66, 67, 3, -1, -1,
+ -1, -1, -1, 74, -1, -1, -1, 13, -1, 23,
+ 24, 17, 83, -1, 85, -1, -1, 31, 32, -1,
+ 26, 35, 28, 37, -1, 31, -1, -1, -1, -1,
+ -1, -1, -1, 39, -1, 41, 42, -1, -1, 12,
+ 13, -1, -1, 49, -1, -1, 52, 53, -1, 22,
+ -1, -1, 58, -1, -1, -1, 29, -1, 64, -1,
+ 33, 34, -1, 36, -1, -1, -1, -1, -1, -1,
+ 43, -1, -1, 79, 47, -1, -1, 3, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 13, -1, -1,
+ -1, 17, 65, 66, 67, -1, 69, -1, -1, -1,
+ 26, -1, 28, -1, -1, -1, -1, 80, 81, 82,
+ -1, -1, -1, 39, -1, 41, 42, -1, -1, -1,
+ -1, -1, -1, 49, -1, -1, 52, 53, -1, -1,
+ -1, -1, 58, -1, -1, -1, -1, -1, 64, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 79, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
+ -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
+ 47, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
+ 67, -1, 69, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 80, 81, 82, -1, -1, -1, -1,
+ -1, -1, -1, -1, 11, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
+ -1, -1, -1, 40, -1, 42, 43, 44, -1, -1,
+ 47, -1, -1, -1, 51, -1, 53, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
+ 67, -1, 69, -1, 71, -1, 73, -1, 75, -1,
+ -1, -1, -1, 80, 81, 82, -1, -1, -1, -1,
+ -1, -1, -1, -1, 7, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, -1, 69, -1, 71, -1,
+ 73, -1, 75, -1, -1, -1, -1, 80, 81, 82,
+ -1, -1, -1, -1, -1, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, -1, 69, -1, 71, -1,
+ 73, 74, 75, -1, -1, -1, -1, 80, 81, 82,
+ -1, -1, -1, -1, -1, -1, -1, -1, 8, -1,
+ -1, 11, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
+ -1, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, -1, 56, -1, -1, -1,
+ -1, -1, -1, -1, -1, 65, 66, 67, -1, 69,
+ -1, 71, -1, 73, -1, 75, -1, -1, -1, -1,
+ 80, 81, 82, -1, -1, -1, -1, -1, -1, -1,
+ -1, 8, -1, -1, 11, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
+ -1, -1, -1, 40, -1, 42, 43, 44, -1, -1,
+ 47, -1, -1, -1, 51, -1, 53, -1, -1, 56,
+ -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
+ 67, -1, 69, -1, 71, -1, 73, -1, 75, -1,
+ -1, -1, -1, 80, 81, 82, -1, -1, -1, -1,
+ -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, -1, 69, -1, 71, -1, 73,
+ -1, 75, -1, -1, -1, -1, 80, 81, 82, -1,
+ -1, -1, -1, -1, -1, -1, -1, 8, -1, -1,
+ 11, 12, 13, -1, -1, -1, -1, -1, -1, -1,
+ -1, 22, -1, -1, -1, -1, -1, -1, 29, -1,
+ -1, -1, 33, 34, -1, 36, -1, -1, -1, 40,
+ -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
+ 51, -1, 53, -1, -1, 56, -1, -1, -1, -1,
+ -1, -1, -1, -1, 65, 66, 67, -1, 69, -1,
+ 71, -1, 73, -1, 75, -1, -1, -1, -1, 80,
+ 81, 82, -1, -1, -1, -1, -1, -1, -1, -1,
+ 8, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, 56, -1,
+ -1, 59, -1, -1, -1, -1, -1, 65, 66, 67,
+ -1, 69, -1, 71, -1, 73, -1, 75, -1, -1,
+ -1, -1, 80, 81, 82, -1, -1, 85, -1, -1,
+ -1, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, 30, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, -1, -1,
+ -1, -1, -1, 61, -1, -1, -1, 65, 66, 67,
+ -1, 69, -1, 71, -1, 73, -1, 75, -1, -1,
+ -1, -1, 80, 81, 82, -1, 84, -1, 86, -1,
+ -1, -1, -1, 4, 5, 6, -1, -1, 9, 10,
+ 11, -1, -1, 14, -1, 16, -1, -1, -1, 20,
+ 21, 22, -1, -1, -1, -1, -1, -1, 29, 30,
+ 31, 32, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 43, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 59, -1,
+ -1, -1, -1, -1, -1, 66, 67, 68, 69, 70,
+ -1, 72, 73, 74, 75, 76, 77, -1, -1, 80,
+ 81, 82, 83, 84, 85, -1, -1, -1, -1, -1,
+ 4, 5, 6, -1, -1, 9, 10, 11, -1, -1,
+ 14, -1, 16, -1, -1, -1, 20, 21, 22, -1,
+ -1, -1, -1, -1, -1, 29, 30, 31, 32, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 43,
+ -1, -1, -1, 47, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 59, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, 69, 70, -1, 72, 73,
+ 74, 75, 76, 77, -1, -1, 80, 81, 82, 83,
+ 84, 85, -1, -1, -1, -1, -1, 4, 5, 6,
+ -1, -1, 9, 10, 11, -1, -1, 14, -1, 16,
+ -1, -1, -1, 20, 21, 22, -1, -1, -1, -1,
+ -1, -1, 29, 30, 31, 32, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
+ 47, -1, -1, -1, -1, -1, -1, -1, 55, -1,
+ -1, -1, 59, -1, -1, -1, -1, -1, 65, 66,
+ 67, 68, 69, 70, -1, 72, 73, 74, 75, 76,
+ 77, -1, -1, 80, 81, 82, 83, 84, 85, -1,
+ -1, -1, -1, -1, 4, -1, -1, -1, -1, 9,
+ -1, 11, 12, 13, 14, -1, -1, -1, -1, -1,
+ -1, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, -1, -1, -1, -1, 59,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, -1, -1,
+ 80, 81, 82, 83, 84, -1, -1, -1, -1, -1,
+ -1, 4, -1, -1, -1, -1, 9, -1, 11, 12,
+ 13, 14, -1, -1, -1, -1, -1, -1, 21, 22,
+ -1, -1, -1, -1, -1, -1, 29, 30, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, 59, -1, 61, -1,
+ -1, -1, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, -1, -1, 80, 81, 82,
+ 83, 84, -1, -1, -1, -1, -1, -1, 4, 5,
+ 6, -1, -1, 9, 10, 11, 12, 13, 14, -1,
+ 16, -1, -1, -1, 20, 21, 22, -1, -1, -1,
+ -1, -1, -1, 29, 30, 31, 32, 33, 34, -1,
+ 36, -1, -1, -1, 40, -1, 42, 43, 44, -1,
+ -1, 47, -1, -1, -1, 51, -1, 53, -1, -1,
+ -1, -1, -1, 59, -1, 61, -1, -1, -1, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, -1, -1, 80, 81, 82, 83, 84, 85,
+ -1, -1, -1, -1, -1, 4, 5, 6, -1, -1,
+ 9, 10, 11, 12, 13, 14, -1, 16, -1, -1,
+ -1, 20, 21, 22, -1, -1, -1, -1, -1, -1,
+ 29, 30, 31, 32, 33, 34, -1, 36, -1, -1,
+ -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
+ -1, -1, 51, -1, 53, -1, 55, -1, -1, -1,
+ 59, -1, 61, -1, -1, -1, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, -1,
+ -1, 80, 81, 82, 83, 84, 85, -1, -1, -1,
+ -1, -1,
+
+ 14, 93, 66, 15, 23, 29, 76, 76, 23, 20,
+ 23, 14, 29, 23, 15, 23, 23, 14, 62, 23,
+ 14, 23, 10, 29, 5, 14, 66, 66, 14, 29,
+ 14, 23, 66, 66, 29, 66, 14, 66, 66, 14,
+ 23, 23, 14, 23, 14, 14, 66, 23, 66, 23,
+ 29, 14, 29, 14, 14, 23, 23, 66, 29, 14,
+ 14, 66, 14, 29, 23, 29, 91, 66, 66, 14,
+ 66, 29, 29, 66, 30, 14, -1, 39, 29, 25,
+ -1, 23, 44, 29, 35, 23, 39, -1, 15, 39,
+ 39, 39, 45, 41, 44, 44, 39, 88, 39, 39,
+ 41, 44, 39, 39, 44, 41, 39, 39, 45, 6,
+ 39, -1, 45, 42, 39, 39, 41, 41, 39, 66,
+ 39, 42, 41, 55, 63, 39, 23, 41, 39, 39,
+ 39, 41, 41, 39, 6, 41, 39, 39, 80, 14,
+ -1, 44, 53, 39, 39, 47, 14, 23, 44, 44,
+ 39, 23, 41, 100, 39, 39, 94, 41, 39, 44,
+ 41, 39, 33, 41, 29, 36, 39, -1, 66, 39,
+ 35, 44, 39, 43, -1, 33, -1, 44, 36, 39,
+ 39, 41, 41, 39, 39, 23, 33, 43, 63, 36,
+ 39, 39, 14, 31, 43, 63, 51, 95, 39, 39,
+ 41, 49, 39, -1, 44, 39, 82, 39, 45, 39,
+ 44, 39, 44, 39, 44, 39, 44, -1, 44, -1,
+ 44, -1, -1, 39, 50, 39, 54, 61, 44, 61,
+ 44, 61, 46, -1, -1, -1, -1, 61, 39, -1,
+ 56, 63, 39, 44, 39, 46, 41, 44, 39, 46,
+ -1, 39, 39, 44, 39, 46, 44, 44, 23, 44,
+ 11, 48, -1, -1, 52, 8, 31, 32, 11, -1,
+ 21, 22, 23, -1, -1, -1, 61, -1, 21, 22,
+ 23, 14, 15, 16, 17, 18, 19, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 23, -1, -1, -1, -1, -1,
+ 29, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1};
+
diff --git a/src/declarative/qml/parser/javascriptgrammar_p.h b/src/declarative/qml/parser/javascriptgrammar_p.h
new file mode 100644
index 0000000..830f533
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptgrammar_p.h
@@ -0,0 +1,200 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef JAVASCRIPTGRAMMAR_P_H
+#define JAVASCRIPTGRAMMAR_P_H
+
+class JavaScriptGrammar
+{
+public:
+ enum {
+ EOF_SYMBOL = 0,
+ REDUCE_HERE = 90,
+ SHIFT_THERE = 89,
+ T_AND = 1,
+ T_AND_AND = 2,
+ T_AND_EQ = 3,
+ T_AUTOMATIC_SEMICOLON = 62,
+ T_BREAK = 4,
+ T_CASE = 5,
+ T_CATCH = 6,
+ T_COLON = 7,
+ T_COMMA = 8,
+ T_CONST = 83,
+ T_CONTINUE = 9,
+ T_DEBUGGER = 84,
+ T_DEFAULT = 10,
+ T_DELETE = 11,
+ T_DIVIDE_ = 12,
+ T_DIVIDE_EQ = 13,
+ T_DO = 14,
+ T_DOT = 15,
+ T_ELSE = 16,
+ T_EQ = 17,
+ T_EQ_EQ = 18,
+ T_EQ_EQ_EQ = 19,
+ T_FALSE = 82,
+ T_FINALLY = 20,
+ T_FOR = 21,
+ T_FUNCTION = 22,
+ T_GE = 23,
+ T_GT = 24,
+ T_GT_GT = 25,
+ T_GT_GT_EQ = 26,
+ T_GT_GT_GT = 27,
+ T_GT_GT_GT_EQ = 28,
+ T_IDENTIFIER = 29,
+ T_IF = 30,
+ T_IMPORT = 88,
+ T_IN = 31,
+ T_INSTANCEOF = 32,
+ T_LBRACE = 33,
+ T_LBRACKET = 34,
+ T_LE = 35,
+ T_LPAREN = 36,
+ T_LT = 37,
+ T_LT_LT = 38,
+ T_LT_LT_EQ = 39,
+ T_MINUS = 40,
+ T_MINUS_EQ = 41,
+ T_MINUS_MINUS = 42,
+ T_MULTILINE_STRING_LITERAL = 86,
+ T_NEW = 43,
+ T_NOT = 44,
+ T_NOT_EQ = 45,
+ T_NOT_EQ_EQ = 46,
+ T_NULL = 80,
+ T_NUMERIC_LITERAL = 47,
+ T_OR = 48,
+ T_OR_EQ = 49,
+ T_OR_OR = 50,
+ T_PLUS = 51,
+ T_PLUS_EQ = 52,
+ T_PLUS_PLUS = 53,
+ T_PROPERTY = 66,
+ T_PUBLIC = 87,
+ T_QUESTION = 54,
+ T_RBRACE = 55,
+ T_RBRACKET = 56,
+ T_REMAINDER = 57,
+ T_REMAINDER_EQ = 58,
+ T_RESERVED_WORD = 85,
+ T_RETURN = 59,
+ T_RPAREN = 60,
+ T_SEMICOLON = 61,
+ T_SIGNAL = 67,
+ T_STAR = 63,
+ T_STAR_EQ = 64,
+ T_STRING_LITERAL = 65,
+ T_SWITCH = 68,
+ T_THIS = 69,
+ T_THROW = 70,
+ T_TILDE = 71,
+ T_TRUE = 81,
+ T_TRY = 72,
+ T_TYPEOF = 73,
+ T_VAR = 74,
+ T_VOID = 75,
+ T_WHILE = 76,
+ T_WITH = 77,
+ T_XOR = 78,
+ T_XOR_EQ = 79,
+
+ ACCEPT_STATE = 588,
+ RULE_COUNT = 323,
+ STATE_COUNT = 589,
+ TERMINAL_COUNT = 91,
+ NON_TERMINAL_COUNT = 102,
+
+ GOTO_INDEX_OFFSET = 589,
+ GOTO_INFO_OFFSET = 2092,
+ GOTO_CHECK_OFFSET = 2092
+ };
+
+ static const char *const spell [];
+ static const int lhs [];
+ static const int rhs [];
+ static const int goto_default [];
+ static const int action_default [];
+ static const int action_index [];
+ static const int action_info [];
+ static const int action_check [];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int *const goto_index = &action_index [GOTO_INDEX_OFFSET];
+ const int *const goto_check = &action_check [GOTO_CHECK_OFFSET];
+
+ const int yyn = goto_index [state] + nt;
+
+ if (yyn < 0 || goto_check [yyn] != nt)
+ return goto_default [nt];
+
+ const int *const goto_info = &action_info [GOTO_INFO_OFFSET];
+ return goto_info [yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
+};
+
+
+#endif // JAVASCRIPTGRAMMAR_P_H
+
diff --git a/src/declarative/qml/parser/javascriptlexer.cpp b/src/declarative/qml/parser/javascriptlexer.cpp
new file mode 100644
index 0000000..ea36a7a
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptlexer.cpp
@@ -0,0 +1,1196 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "javascriptengine_p.h"
+#include "javascriptlexer_p.h"
+#include "javascriptgrammar_p.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+extern double qstrtod(const char *s00, char const **se, bool *ok);
+
+#define shiftWindowsLineBreak() \
+ do { \
+ if (((current == '\r') && (next1 == '\n')) \
+ || ((current == '\n') && (next1 == '\r'))) { \
+ shift(1); \
+ } \
+ } \
+ while (0)
+
+namespace JavaScript {
+extern double integerFromString(const char *buf, int size, int radix);
+}
+
+using namespace JavaScript;
+
+Lexer::Lexer(Engine *eng)
+ : driver(eng),
+ yylineno(0),
+ done(false),
+ size8(128), size16(128),
+ pos8(0), pos16(0),
+ terminator(false),
+ restrKeyword(false),
+ delimited(false),
+ stackToken(-1),
+ state(Start),
+ pos(0),
+ code(0), length(0),
+ yycolumn(0),
+ startpos(0),
+ startlineno(0), startcolumn(0),
+ bol(true),
+ current(0), next1(0), next2(0), next3(0),
+ err(NoError),
+ wantRx(false),
+ check_reserved(true),
+ parenthesesState(IgnoreParentheses),
+ parenthesesCount(0),
+ prohibitAutomaticSemicolon(false)
+{
+ driver->setLexer(this);
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new QChar[size16];
+ pattern = 0;
+ flags = 0;
+
+}
+
+Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+void Lexer::setCode(const QString &c, int lineno)
+{
+ errmsg = QString();
+ yylineno = lineno;
+ yycolumn = 1;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c.unicode();
+ length = c.length();
+ bol = true;
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void Lexer::shift(uint p)
+{
+ while (p--) {
+ ++pos;
+ ++yycolumn;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int Lexer::findReservedWord(const QChar *c, int size) const
+{
+ switch (size) {
+ case 2: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
+ return JavaScriptGrammar::T_DO;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
+ return JavaScriptGrammar::T_IF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_IN;
+ } break;
+
+ case 3: {
+ if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_FOR;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
+ return JavaScriptGrammar::T_NEW;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
+ return JavaScriptGrammar::T_TRY;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_VAR;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 4: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_CASE;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_ELSE;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_THIS;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
+ return JavaScriptGrammar::T_VOID;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
+ return JavaScriptGrammar::T_WITH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_TRUE;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
+ return JavaScriptGrammar::T_NULL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 5: {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('k'))
+ return JavaScriptGrammar::T_BREAK;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h'))
+ return JavaScriptGrammar::T_CATCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w'))
+ return JavaScriptGrammar::T_THROW;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_WHILE;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_CONST;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_FALSE;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
+ && c[4] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 6: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_DELETE;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_RETURN;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
+ return JavaScriptGrammar::T_SWITCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
+ return JavaScriptGrammar::T_TYPEOF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_IMPORT;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l'))
+ return JavaScriptGrammar::T_SIGNAL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return JavaScriptGrammar::T_PUBLIC;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
+ && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 7: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_DEFAULT;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('y'))
+ return JavaScriptGrammar::T_FINALLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
+ && c[6] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
+ && c[6] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 8: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_CONTINUE;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_FUNCTION;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_DEBUGGER;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y'))
+ return JavaScriptGrammar::T_PROPERTY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 9: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
+ && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
+ && c[8] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('d'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 10: {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
+ return JavaScriptGrammar::T_INSTANCEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 12: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
+ && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ } // switch
+
+ return -1;
+}
+
+int Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ ushort stringType = 0; // either single or double quotes
+ bool multiLineString = false;
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = -1;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ recordStartPos();
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ recordStartPos();
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ syncProhibitAutomaticSemicolon();
+ if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
+ // automatic semicolon insertion if program incomplete
+ token = JavaScriptGrammar::T_SEMICOLON;
+ stackToken = 0;
+ setDone(Other);
+ } else {
+ setDone(Eof);
+ }
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ terminator = true;
+ syncProhibitAutomaticSemicolon();
+ if (restrKeyword) {
+ token = JavaScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ recordStartPos();
+ state = InString;
+ multiLineString = false;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ recordStartPos();
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ recordStartPos();
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ recordStartPos();
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ recordStartPos();
+ record8(current);
+ state = InDecimal;
+ } else {
+ recordStartPos();
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ if (terminator && !delimited && !prohibitAutomaticSemicolon
+ && (token == JavaScriptGrammar::T_PLUS_PLUS
+ || token == JavaScriptGrammar::T_MINUS_MINUS)) {
+ // automatic semicolon insertion
+ stackToken = token;
+ token = JavaScriptGrammar::T_SEMICOLON;
+ }
+ setDone(Other);
+ }
+ else {
+ setDone(Bad);
+ err = IllegalCharacter;
+ errmsg = QLatin1String("Illegal character");
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (isLineTerminator()) {
+ multiLineString = true;
+ record16(current);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ err = UnclosedStringLiteral;
+ errmsg = QLatin1String("Unclosed string at end of line");
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) &&
+ isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ err = IllegalEscapeSequence;
+ errmsg = QLatin1String("Illegal escape squence");
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ } else {
+ record16(singleEscape(current));
+ }
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(QLatin1Char(convertHex(current, next1)));
+ shift(1);
+ } else if (current == stringType) {
+ record16(QLatin1Char('x'));
+ shift(1);
+ setDone(String);
+ } else {
+ record16(QLatin1Char('x'));
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16(QLatin1Char('u'));
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ err = IllegalUnicodeEscapeSequence;
+ errmsg = QLatin1String("Illegal unicode escape sequence");
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ terminator = true;
+ bol = true;
+ if (restrKeyword) {
+ token = JavaScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ } else
+ state = Start;
+ } else if (current == 0) {
+ setDone(Eof);
+ }
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ err = UnclosedComment;
+ errmsg = QLatin1String("Unclosed comment at end of file");
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current))
+ record8(current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Octal);
+ }
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else {
+ setDone(Bad);
+ err = IllegalExponentIndicator;
+ errmsg = QLatin1String("Illegal syntax for exponential number");
+ }
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Number);
+ }
+ break;
+ default:
+ Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+ }
+
+ if (state == Number) {
+ // CSS-style suffix for numeric literals
+
+ flags = noSuffix;
+
+ const ushort c = QChar::toLower(current);
+ const ushort n1 = QChar::toLower(next1);
+ const ushort n2 = QChar::toLower(next2);
+ const ushort n3 = QChar::toLower(next3);
+
+ if (c == 'e' && n1 == 'm') {
+ flags = emSuffix;
+ shift(2);
+ } else if (c == 'e' && n1 == 'x') {
+ flags = exSuffix;
+ shift(2);
+ } else if (c == 'p' && n1 == 'x') {
+ flags = pxSuffix;
+ shift(2);
+ } else if (c == 'c' && n1 == 'm') {
+ flags = cmSuffix;
+ shift(2);
+ } else if (c == 'm' && n1 == 'm') {
+ flags = mmSuffix;
+ shift(2);
+ } else if (c == 'i' && n1 == 'n') {
+ flags = inSuffix;
+ shift(2);
+ } else if (c == 'p' && n1 == 't') {
+ flags = ptSuffix;
+ shift(2);
+ } else if (c == 'p' && n1 == 'c') {
+ flags = pcSuffix;
+ shift(1);
+ } else if (c == 'd' && n1 == 'e' && n2 == 'g') {
+ flags = degSuffix;
+ shift(3);
+ } else if (c == 'r' && n1 == 'a' && n2 == 'd') {
+ flags = radSuffix;
+ shift(3);
+ } else if (c == 'g' && n1 == 'r' && n2 == 'a' && n3 == 'd') {
+ flags = gradSuffix;
+ shift(4);
+ } else if (c == 'm' && n1 == 's') {
+ flags = msSuffix;
+ shift(2);
+ } else if (c == 's') {
+ flags = sSuffix;
+ shift(1);
+ } else if (c == 'h' && n1 == 'z') {
+ flags = hzSuffix;
+ shift(2);
+ } else if (c == 'k' && n1 == 'h' && n2 == 'z') {
+ flags = khzSuffix;
+ shift(3);
+ }
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current)) {
+ state = Bad;
+ err = IllegalIdentifier;
+ errmsg = QLatin1String("Identifier cannot start with numeric literal");
+ }
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+ double dval = 0;
+ if (state == Number) {
+ dval = qstrtod(buffer8, 0, 0);
+ } else if (state == Hex) { // scan hex numbers
+ dval = integerFromString(buffer8, pos8, 16);
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ dval = integerFromString(buffer8, pos8, 8);
+ state = Number;
+ }
+
+ restrKeyword = false;
+ delimited = false;
+
+ switch (parenthesesState) {
+ case IgnoreParentheses:
+ break;
+ case CountParentheses:
+ if (token == JavaScriptGrammar::T_RPAREN) {
+ --parenthesesCount;
+ if (parenthesesCount == 0)
+ parenthesesState = BalancedParentheses;
+ } else if (token == JavaScriptGrammar::T_LPAREN) {
+ ++parenthesesCount;
+ }
+ break;
+ case BalancedParentheses:
+ parenthesesState = IgnoreParentheses;
+ break;
+ }
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if (token == JavaScriptGrammar::T_RBRACE || token == JavaScriptGrammar::T_SEMICOLON)
+ delimited = true;
+ return token;
+ case Identifier:
+ if ((token = findReservedWord(buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return JavaScriptGrammar::T_IDENTIFIER;
+ }
+ if (token == JavaScriptGrammar::T_CONTINUE || token == JavaScriptGrammar::T_BREAK
+ || token == JavaScriptGrammar::T_RETURN || token == JavaScriptGrammar::T_THROW) {
+ restrKeyword = true;
+ } else if (token == JavaScriptGrammar::T_IF || token == JavaScriptGrammar::T_FOR
+ || token == JavaScriptGrammar::T_WHILE || token == JavaScriptGrammar::T_WITH) {
+ parenthesesState = CountParentheses;
+ parenthesesCount = 0;
+ } else if (token == JavaScriptGrammar::T_DO) {
+ parenthesesState = BalancedParentheses;
+ }
+ return token;
+ case String:
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return multiLineString?JavaScriptGrammar::T_MULTILINE_STRING_LITERAL:JavaScriptGrammar::T_STRING_LITERAL;
+ case Number:
+ qsyylval.dval = dval;
+ return JavaScriptGrammar::T_NUMERIC_LITERAL;
+ case Bad:
+ return -1;
+ default:
+ Q_ASSERT(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool Lexer::isIdentLetter(ushort c)
+{
+ /* TODO: allow other legitimate unicode chars */
+ return ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c == '$'
+ || c == '_');
+}
+
+bool Lexer::isDecimalDigit(ushort c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool Lexer::isHexDigit(ushort c) const
+{
+ return ((c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F'));
+}
+
+bool Lexer::isOctalDigit(ushort c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int Lexer::matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return JavaScriptGrammar::T_GT_GT_GT_EQ;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_EQ_EQ_EQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_NOT_EQ_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return JavaScriptGrammar::T_GT_GT_GT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_LT_LT_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_GT_GT_EQ;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_NOT_EQ;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ return JavaScriptGrammar::T_PLUS_PLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ return JavaScriptGrammar::T_MINUS_MINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_EQ_EQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_PLUS_EQ;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_MINUS_EQ;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_STAR_EQ;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_DIVIDE_EQ;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_AND_EQ;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_XOR_EQ;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_REMAINDER_EQ;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_OR_EQ;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return JavaScriptGrammar::T_LT_LT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return JavaScriptGrammar::T_GT_GT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return JavaScriptGrammar::T_AND_AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return JavaScriptGrammar::T_OR_OR;
+ }
+
+ switch(c1) {
+ case '=': shift(1); return JavaScriptGrammar::T_EQ;
+ case '>': shift(1); return JavaScriptGrammar::T_GT;
+ case '<': shift(1); return JavaScriptGrammar::T_LT;
+ case ',': shift(1); return JavaScriptGrammar::T_COMMA;
+ case '!': shift(1); return JavaScriptGrammar::T_NOT;
+ case '~': shift(1); return JavaScriptGrammar::T_TILDE;
+ case '?': shift(1); return JavaScriptGrammar::T_QUESTION;
+ case ':': shift(1); return JavaScriptGrammar::T_COLON;
+ case '.': shift(1); return JavaScriptGrammar::T_DOT;
+ case '+': shift(1); return JavaScriptGrammar::T_PLUS;
+ case '-': shift(1); return JavaScriptGrammar::T_MINUS;
+ case '*': shift(1); return JavaScriptGrammar::T_STAR;
+ case '/': shift(1); return JavaScriptGrammar::T_DIVIDE_;
+ case '&': shift(1); return JavaScriptGrammar::T_AND;
+ case '|': shift(1); return JavaScriptGrammar::T_OR;
+ case '^': shift(1); return JavaScriptGrammar::T_XOR;
+ case '%': shift(1); return JavaScriptGrammar::T_REMAINDER;
+ case '(': shift(1); return JavaScriptGrammar::T_LPAREN;
+ case ')': shift(1); return JavaScriptGrammar::T_RPAREN;
+ case '{': shift(1); return JavaScriptGrammar::T_LBRACE;
+ case '}': shift(1); return JavaScriptGrammar::T_RBRACE;
+ case '[': shift(1); return JavaScriptGrammar::T_LBRACKET;
+ case ']': shift(1); return JavaScriptGrammar::T_RBRACKET;
+ case ';': shift(1); return JavaScriptGrammar::T_SEMICOLON;
+
+ default: return -1;
+ }
+}
+
+ushort Lexer::singleEscape(ushort c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+ushort Lexer::convertOctal(ushort c1, ushort c2,
+ ushort c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char Lexer::convertHex(ushort c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char Lexer::convertHex(ushort c1, ushort c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+QChar Lexer::convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ return QChar((convertHex(c3) << 4) + convertHex(c4),
+ (convertHex(c1) << 4) + convertHex(c2));
+}
+
+void Lexer::record8(ushort c)
+{
+ Q_ASSERT(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void Lexer::record16(QChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ QChar *tmp = new QChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(QChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+void Lexer::recordStartPos()
+{
+ startpos = pos;
+ startlineno = yylineno;
+ startcolumn = yycolumn;
+}
+
+bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ if (prefix == EqualPrefix)
+ record16(QLatin1Char('='));
+
+ while (1) {
+ if (isLineTerminator() || current == 0) {
+ errmsg = QLatin1String("Unterminated regular expression literal");
+ return false;
+ }
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape = !lastWasEscape && (current == '\\');
+ }
+ else {
+ if (driver)
+ pattern = driver->intern(buffer16, pos16);
+ else
+ pattern = 0;
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ flags = 0;
+ while (isIdentLetter(current)) {
+ int flag = Ecma::RegExp::flagFromChar(current);
+ if (flag == 0) {
+ errmsg = QString::fromLatin1("Invalid regular expression flag '%0'")
+ .arg(QChar(current));
+ return false;
+ }
+ flags |= flag;
+ record16(current);
+ shift(1);
+ }
+
+ return true;
+}
+
+void Lexer::syncProhibitAutomaticSemicolon()
+{
+ if (parenthesesState == BalancedParentheses) {
+ // we have seen something like "if (foo)", which means we should
+ // never insert an automatic semicolon at this point, since it would
+ // then be expanded into an empty statement (ECMA-262 7.9.1)
+ prohibitAutomaticSemicolon = true;
+ parenthesesState = IgnoreParentheses;
+ } else {
+ prohibitAutomaticSemicolon = false;
+ }
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptlexer_p.h b/src/declarative/qml/parser/javascriptlexer_p.h
new file mode 100644
index 0000000..a47c1ae
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptlexer_p.h
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTLEXER_P_H
+#define JAVASCRIPTLEXER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+
+
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+class Engine;
+class NameId;
+
+class Lexer
+{
+public:
+ Lexer(Engine *eng);
+ ~Lexer();
+
+ void setCode(const QString &c, int lineno);
+ int lex();
+
+ int currentLineNo() const { return yylineno; }
+ int currentColumnNo() const { return yycolumn; }
+
+ int tokenOffset() const { return startpos; }
+ int tokenLength() const { return pos - startpos; }
+
+ int startLineNo() const { return startlineno; }
+ int startColumnNo() const { return startcolumn; }
+
+ int endLineNo() const { return currentLineNo(); }
+ int endColumnNo() const
+ { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ enum Suffix {
+ noSuffix,
+ emSuffix,
+ exSuffix,
+ pxSuffix,
+ cmSuffix,
+ mmSuffix,
+ inSuffix,
+ ptSuffix,
+ pcSuffix,
+ degSuffix,
+ radSuffix,
+ gradSuffix,
+ msSuffix,
+ sSuffix,
+ hzSuffix,
+ khzSuffix
+ };
+
+ enum Error {
+ NoError,
+ IllegalCharacter,
+ UnclosedStringLiteral,
+ IllegalEscapeSequence,
+ IllegalUnicodeEscapeSequence,
+ UnclosedComment,
+ IllegalExponentIndicator,
+ IllegalIdentifier
+ };
+
+ enum ParenthesesState {
+ IgnoreParentheses,
+ CountParentheses,
+ BalancedParentheses
+ };
+
+ enum RegExpBodyPrefix {
+ NoPrefix,
+ EqualPrefix
+ };
+
+ bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+
+ NameId *pattern;
+ int flags;
+
+ State lexerState() const
+ { return state; }
+
+ QString errorMessage() const
+ { return errmsg; }
+ void setErrorMessage(const QString &err)
+ { errmsg = err; }
+ void setErrorMessage(const char *err)
+ { setErrorMessage(QString::fromLatin1(err)); }
+
+ Error error() const
+ { return err; }
+ void clearError()
+ { err = NoError; }
+
+private:
+ Engine *driver;
+ int yylineno;
+ bool done;
+ char *buffer8;
+ QChar *buffer16;
+ uint size8, size16;
+ uint pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ uint pos;
+ void shift(uint p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(ushort c) const;
+ bool isOctalDigit(ushort c) const;
+
+ int matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ ushort singleEscape(ushort c) const;
+ ushort convertOctal(ushort c1, ushort c2,
+ ushort c3) const;
+public:
+ static unsigned char convertHex(ushort c1);
+ static unsigned char convertHex(ushort c1, ushort c2);
+ static QChar convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ static bool isIdentLetter(ushort c);
+ static bool isDecimalDigit(ushort c);
+
+ inline int ival() const { return qsyylval.ival; }
+ inline double dval() const { return qsyylval.dval; }
+ inline NameId *ustr() const { return qsyylval.ustr; }
+
+ const QChar *characterBuffer() const { return buffer16; }
+ int characterCount() const { return pos16; }
+
+private:
+ void record8(ushort c);
+ void record16(QChar c);
+ void recordStartPos();
+
+ int findReservedWord(const QChar *buffer, int size) const;
+
+ void syncProhibitAutomaticSemicolon();
+
+ const QChar *code;
+ uint length;
+ int yycolumn;
+ int startpos;
+ int startlineno;
+ int startcolumn;
+ int bol; // begin of line
+
+ union {
+ int ival;
+ double dval;
+ NameId *ustr;
+ } qsyylval;
+
+ // current and following unicode characters
+ ushort current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ QString errmsg;
+ Error err;
+
+ bool wantRx;
+ bool check_reserved;
+
+ ParenthesesState parenthesesState;
+ int parenthesesCount;
+ bool prohibitAutomaticSemicolon;
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptmemorypool_p.h b/src/declarative/qml/parser/javascriptmemorypool_p.h
new file mode 100644
index 0000000..cff7677
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptmemorypool_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTMEMORYPOOL_P_H
+#define JAVASCRIPTMEMORYPOOL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qshareddata.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+class MemoryPool : public QSharedData
+{
+public:
+ enum { maxBlockCount = -1 };
+ enum { defaultBlockSize = 1 << 12 };
+
+ MemoryPool() {
+ m_blockIndex = maxBlockCount;
+ m_currentIndex = 0;
+ m_storage = 0;
+ m_currentBlock = 0;
+ m_currentBlockSize = 0;
+ }
+
+ virtual ~MemoryPool() {
+ for (int index = 0; index < m_blockIndex + 1; ++index)
+ qFree(m_storage[index]);
+
+ qFree(m_storage);
+ }
+
+ char *allocate(int bytes) {
+ bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment)
+ if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) {
+ ++m_blockIndex;
+ m_currentBlockSize = defaultBlockSize << m_blockIndex;
+
+ m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex)));
+ m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize));
+ ::memset(m_currentBlock, 0, m_currentBlockSize);
+
+ m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned
+ Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize);
+ }
+
+ char *p = reinterpret_cast<char *>
+ (m_currentBlock + m_currentIndex);
+
+ m_currentIndex += bytes;
+
+ return p;
+ }
+
+ int bytesAllocated() const {
+ int bytes = 0;
+ for (int index = 0; index < m_blockIndex; ++index)
+ bytes += (defaultBlockSize << index);
+ bytes += m_currentIndex;
+ return bytes;
+ }
+
+private:
+ int m_blockIndex;
+ int m_currentIndex;
+ char *m_currentBlock;
+ int m_currentBlockSize;
+ char **m_storage;
+
+private:
+ Q_DISABLE_COPY(MemoryPool)
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptnodepool_p.h b/src/declarative/qml/parser/javascriptnodepool_p.h
new file mode 100644
index 0000000..cb56fbb
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptnodepool_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTNODEPOOL_P_H
+#define JAVASCRIPTNODEPOOL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QHash>
+#include <QtCore/QString>
+
+#include "javascriptmemorypool_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+namespace AST {
+class Node;
+} // namespace AST
+
+class Code;
+class CompilationUnit;
+class Engine;
+
+template <typename NodeType>
+inline NodeType *makeAstNode(MemoryPool *storage)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType();
+ return node;
+}
+
+template <typename NodeType, typename Arg1>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4);
+ return node;
+}
+
+class NodePool : public MemoryPool
+{
+public:
+ NodePool(const QString &fileName, Engine *engine);
+ virtual ~NodePool();
+
+ Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation);
+
+ inline QString fileName() const { return m_fileName; }
+ inline Engine *engine() const { return m_engine; }
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ inline qint64 id() const { return m_id; }
+#endif
+
+private:
+ QHash<AST::Node*, Code*> m_codeCache;
+ QString m_fileName;
+ Engine *m_engine;
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ qint64 m_id;
+#endif
+
+private:
+ Q_DISABLE_COPY(NodePool)
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptparser.cpp b/src/declarative/qml/parser/javascriptparser.cpp
new file mode 100644
index 0000000..34ecd0e
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptparser.cpp
@@ -0,0 +1,1716 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtDebug>
+
+#include <string.h>
+
+#include "javascriptengine_p.h"
+#include "javascriptlexer_p.h"
+#include "javascriptast_p.h"
+#include "javascriptnodepool_p.h"
+
+
+
+#include "javascriptparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+using namespace JavaScript;
+
+QT_BEGIN_NAMESPACE
+
+void Parser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(Engine *driver, int token)
+{
+ return token == JavaScriptGrammar::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+Parser::Parser(Engine *engine):
+ driver(engine),
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+Parser::~Parser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
+{
+ QVarLengthArray<NameId *, 4> nameIds;
+ QVarLengthArray<AST::SourceLocation, 4> locations;
+
+ AST::ExpressionNode *it = expr;
+ while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) {
+ nameIds.append(m->name);
+ locations.append(m->identifierToken);
+ it = m->base;
+ }
+
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
+ AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name);
+ q->identifierToken = idExpr->identifierToken;
+
+ AST::UiQualifiedId *currentId = q;
+ for (int i = nameIds.size() - 1; i != -1; --i) {
+ currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]);
+ currentId->identifierToken = locations[i];
+ }
+
+ return currentId->finish();
+ }
+
+ return 0;
+}
+
+bool Parser::parse()
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ first_token = last_token = 0;
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+
+case 0: {
+ program = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+ sym(1).UiProgram = program;
+} break;
+
+case 2: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+
+case 3: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+
+case 4: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+
+case 6: {
+ AST::UiImport *node = makeAstNode<AST::UiImport>(driver->nodePool(), sym(2).sval);
+ node->importToken = loc(1);
+ node->fileNameToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 7: {
+ sym(1).Node = 0;
+} break;
+
+case 8: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 9: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 10: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+
+case 11: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 12: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(3).UiObjectMember);
+ sym(1).Node = node;
+} break;
+
+case 13: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 14: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 15: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+} break;
+
+case 17: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(4).UiObjectMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 18: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 20: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 21: {
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } else {
+ sym(1).Node = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2),
+ QLatin1String("Expected a type name after token `:'")));
+
+ return false; // ### recover
+ }
+} break;
+case 22:case 23:case 24:case 25:case 26:case 27:
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 28:
+
+case 29: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+
+case 31: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 33: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 35: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 37: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 39: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 40: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 41: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+case 42:
+case 43:
+{
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 45: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 46: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 47: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 48: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 49: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 50: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 51: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 52: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 53: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 54: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 55: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 56: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 57: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 58: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 59: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 60: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ sym(4).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 61: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 62: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 63: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 64: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 65: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 66: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression);
+} break;
+
+case 67: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression);
+} break;
+
+case 68: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList,
+ (AST::Elision *) 0, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 69: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(),
+ sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 70: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 71: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 72: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 73: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 74: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 75:
+case 76: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 77: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 78: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 79: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 80:
+
+case 81:
+
+case 82:
+
+case 83:
+
+case 84:
+
+case 85:
+
+case 86:
+
+case 87:
+
+case 88:
+
+case 89:
+
+case 90:
+
+case 91:
+
+case 92:
+
+case 93:
+
+case 94:
+
+case 95:
+
+case 96:
+
+case 97:
+
+case 98:
+
+case 99:
+
+case 100:
+
+case 101:
+
+case 102:
+
+case 103:
+
+case 104:
+
+case 105:
+
+case 106:
+
+case 107:
+
+case 108:
+
+case 109:
+
+case 110:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+
+case 115: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 116: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 117: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 119: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 120: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 121: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 122: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 123: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 124: {
+ sym(1).Node = 0;
+} break;
+
+case 125: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+
+case 126: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+
+case 127: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 131: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 132: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 134: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 135: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 136: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 137: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 138: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 139: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 140: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 141: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 142: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 144: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 145: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 146: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 148: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 149: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 151: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 152: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 153: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 155: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 156: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 157: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 158: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 159: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 160: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 162: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 163: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 164: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 165: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 166: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 168: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 169: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 170: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 171: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 173: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 174: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 175: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 176: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 178: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 180: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 182: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 184: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 186: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 188: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 190: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 192: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 194: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 196: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 198: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 200: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 202: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 204: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 205: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+
+case 206: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+
+case 207: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+
+case 208: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+
+case 209: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+
+case 210: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+
+case 211: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+
+case 212: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+
+case 213: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+
+case 214: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+
+case 215: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+
+case 216: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+
+case 218: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 219: {
+ sym(1).Node = 0;
+} break;
+
+case 222: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 223: {
+ sym(1).Node = 0;
+} break;
+
+case 240: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 241: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 242: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+
+case 243: {
+ sym(1).Node = 0;
+} break;
+
+case 244: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+
+case 246: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 247: {
+ sym(1).ival = T_CONST;
+} break;
+
+case 248: {
+ sym(1).ival = T_VAR;
+} break;
+
+case 249: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 250: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 251: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 252: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+
+case 253: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 254: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 255: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 256: {
+ sym(1).Node = 0;
+} break;
+
+case 258: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 259: {
+ sym(1).Node = 0;
+} break;
+
+case 261: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 263: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 264: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 265: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 267: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 268: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 269: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 270: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+
+case 271: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 272: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 274: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 276: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 278: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 280: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 282: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 283: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 284: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 285: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 286: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 287: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+
+case 288: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+
+case 289: {
+ sym(1).Node = 0;
+} break;
+
+case 290: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+
+case 291: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 292: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+case 293:
+case 294: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 295: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 297: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 298: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 299: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 300: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 301: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 302: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 304: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 305: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 306: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 307: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 308: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 309: {
+ sym(1).Node = 0;
+} break;
+
+case 310: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+
+case 311: {
+ sym(1).Node = 0;
+} break;
+
+case 313: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+
+case 314: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+
+case 315: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+
+case 316: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 317: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+
+case 318: {
+ sym(1).sval = 0;
+} break;
+
+case 320: {
+ sym(1).Node = 0;
+} break;
+
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = QString::fromUtf8("Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = QString::fromUtf8("Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptparser_p.h b/src/declarative/qml/parser/javascriptparser_p.h
new file mode 100644
index 0000000..2ae4c34
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptparser_p.h
@@ -0,0 +1,207 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+#ifndef JAVASCRIPTPARSER_P_H
+#define JAVASCRIPTPARSER_P_H
+
+#include "javascriptgrammar_p.h"
+#include "javascriptast_p.h"
+#include "javascriptengine_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace JavaScript {
+
+class Engine;
+class NameId;
+
+class Parser: protected JavaScriptGrammar
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ NameId *sval;
+ AST::ArgumentList *ArgumentList;
+ AST::CaseBlock *CaseBlock;
+ AST::CaseClause *CaseClause;
+ AST::CaseClauses *CaseClauses;
+ AST::Catch *Catch;
+ AST::DefaultClause *DefaultClause;
+ AST::ElementList *ElementList;
+ AST::Elision *Elision;
+ AST::ExpressionNode *Expression;
+ AST::Finally *Finally;
+ AST::FormalParameterList *FormalParameterList;
+ AST::FunctionBody *FunctionBody;
+ AST::FunctionDeclaration *FunctionDeclaration;
+ AST::Node *Node;
+ AST::PropertyName *PropertyName;
+ AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ AST::SourceElement *SourceElement;
+ AST::SourceElements *SourceElements;
+ AST::Statement *Statement;
+ AST::StatementList *StatementList;
+ AST::Block *Block;
+ AST::VariableDeclaration *VariableDeclaration;
+ AST::VariableDeclarationList *VariableDeclarationList;
+
+ AST::UiProgram *UiProgram;
+ AST::UiImportList *UiImportList;
+ AST::UiImport *UiImport;
+ AST::UiPublicMember *UiPublicMember;
+ AST::UiObjectDefinition *UiObjectDefinition;
+ AST::UiObjectInitializer *UiObjectInitializer;
+ AST::UiObjectBinding *UiObjectBinding;
+ AST::UiScriptBinding *UiScriptBinding;
+ AST::UiArrayBinding *UiArrayBinding;
+ AST::UiObjectMember *UiObjectMember;
+ AST::UiObjectMemberList *UiObjectMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ bool parse();
+
+ AST::UiProgram *ast()
+ { return program; }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+ AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
+
+protected:
+ Engine *driver;
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ AST::SourceLocation *location_stack;
+
+ AST::UiProgram *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ AST::SourceLocation loc;
+ };
+
+ double yylval;
+ AST::SourceLocation yylloc;
+ AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+} // end of namespace JavaScript
+
+
+
+#define J_SCRIPT_REGEXPLITERAL_RULE1 54
+
+#define J_SCRIPT_REGEXPLITERAL_RULE2 55
+
+QT_END_NAMESPACE
+
+
+
+#endif // JAVASCRIPTPARSER_P_H
diff --git a/src/declarative/qml/parser/javascriptprettypretty.cpp b/src/declarative/qml/parser/javascriptprettypretty.cpp
new file mode 100644
index 0000000..0342b39
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptprettypretty.cpp
@@ -0,0 +1,1334 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptprettypretty_p.h"
+
+
+
+#include "javascriptengine_p.h"
+
+
+
+
+#include "javascriptast_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+#include <QtCore/QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+QString numberToString(double value);
+}
+
+using namespace JavaScript;
+
+PrettyPretty::PrettyPretty(QTextStream &o):
+ out(o), m_indentLevel(0)
+{
+}
+
+PrettyPretty::~PrettyPretty()
+{
+}
+
+void PrettyPretty::acceptAsBlock(AST::Node *node)
+{
+ out << "{";
+ pushIndentLevel();
+ newlineAndIndent();
+ accept(node);
+ popIndentLevel();
+ newlineAndIndent();
+ out << "}";
+}
+
+int PrettyPretty::operatorPrecedenceLevel(int op)
+{
+ switch (op) {
+ case QSOperator::Div:
+ case QSOperator::Mod:
+ case QSOperator::Mul:
+ return 5;
+ case QSOperator::Add:
+ case QSOperator::Sub:
+ return 6;
+ case QSOperator::LShift:
+ case QSOperator::RShift:
+ case QSOperator::URShift:
+ return 7;
+ case QSOperator::Ge:
+ case QSOperator::Gt:
+ case QSOperator::In:
+ case QSOperator::InstanceOf:
+ case QSOperator::Le:
+ case QSOperator::Lt:
+ return 8;
+ case QSOperator::Equal:
+ case QSOperator::NotEqual:
+ case QSOperator::StrictEqual:
+ case QSOperator::StrictNotEqual:
+ return 9;
+ case QSOperator::BitAnd:
+ return 10;
+ case QSOperator::BitXor:
+ return 11;
+ case QSOperator::BitOr:
+ return 12;
+ case QSOperator::And:
+ return 13;
+ case QSOperator::Or:
+ return 14;
+ case QSOperator::InplaceAnd:
+ case QSOperator::InplaceSub:
+ case QSOperator::InplaceDiv:
+ case QSOperator::InplaceAdd:
+ case QSOperator::InplaceLeftShift:
+ case QSOperator::InplaceMod:
+ case QSOperator::InplaceMul:
+ case QSOperator::InplaceOr:
+ case QSOperator::InplaceRightShift:
+ case QSOperator::InplaceURightShift:
+ case QSOperator::InplaceXor:
+ case QSOperator::Assign:
+ return 16;
+ default:
+ Q_ASSERT_X(false, "PrettyPretty::operatorPrecedenceLevel()", "bad operator");
+ }
+ return 0;
+}
+
+int PrettyPretty::compareOperatorPrecedence(int op1, int op2)
+{
+ int prec1 = operatorPrecedenceLevel(op1);
+ int prec2 = operatorPrecedenceLevel(op2);
+ if (prec1 == prec2)
+ return 0;
+ if (prec1 > prec2)
+ return -1;
+ return 1;
+}
+
+QTextStream &PrettyPretty::operator () (AST::Node *node, int level)
+{
+ int was = indentLevel(level);
+ accept(node);
+ indentLevel(was);
+ return out;
+}
+
+QTextStream &PrettyPretty::newlineAndIndent()
+{
+ enum { IND = 4 };
+ out << endl << QString().fill(QLatin1Char(' '), m_indentLevel * IND);
+ return out;
+}
+
+void PrettyPretty::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+bool PrettyPretty::visit(AST::ThisExpression *node)
+{
+ Q_UNUSED(node);
+ out << "this";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::ThisExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::IdentifierExpression *node)
+{
+ out << Engine::toString(node->name);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::IdentifierExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NullExpression *node)
+{
+ Q_UNUSED(node);
+ out << "null";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NullExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TrueLiteral *node)
+{
+ Q_UNUSED(node);
+ out << "true";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::TrueLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FalseLiteral *node)
+{
+ Q_UNUSED(node);
+ out << "false";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FalseLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StringLiteral *node)
+{
+ QString lit = Engine::toString(node->value);
+ lit.replace(QLatin1String("\\"), QLatin1String("\\\\"));
+ out << "\"" << lit << "\"";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::StringLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NumericLiteral *node)
+{
+ out << JavaScript::numberToString(node->value);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::NumericLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::RegExpLiteral *node)
+{
+ out << "/" << Engine::toString(node->pattern) << "/";
+ if (node->flags)
+ out << JavaScript::Ecma::RegExp::flagsToString(node->flags);
+
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::RegExpLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ArrayLiteral *node)
+{
+ out << "[";
+ accept(node->elements);
+ accept(node->elision);
+ out << "]";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ArrayLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ObjectLiteral *node)
+{
+ out << "{";
+ if (node->properties) {
+ pushIndentLevel();
+ AST::PropertyNameAndValueList *prop;
+ for (prop = node->properties; prop != 0; prop = prop->next) {
+ newlineAndIndent();
+ accept(prop);
+ if (prop->next)
+ out << ",";
+ }
+ popIndentLevel();
+ newlineAndIndent();
+ }
+ out << "}";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ObjectLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ElementList *node)
+{
+ accept(node->elision);
+ accept(node->expression);
+ for (node = node->next; node != 0; node = node->next) {
+ out << ", ";
+ accept(node->elision);
+ accept(node->expression);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ElementList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Elision *node)
+{
+ out << ", ";
+ for (AST::Elision *eit = node->next; eit != 0; eit = eit->next)
+ out << ", ";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::Elision *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PropertyNameAndValueList *node)
+{
+ accept(node->name);
+ out << ": ";
+ accept(node->value);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::IdentifierPropertyName *node)
+{
+ out << Engine::toString(node->id);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::IdentifierPropertyName *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StringLiteralPropertyName *node)
+{
+ QString lit = Engine::toString(node->id);
+ lit.replace(QLatin1String("\\"), QLatin1String("\\\\"));
+ out << lit;
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::StringLiteralPropertyName *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node)
+{
+ out << node->id;
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ArrayMemberExpression *node)
+{
+ accept(node->base);
+ out << "[";
+ accept(node->expression);
+ out << "]";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ArrayMemberExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FieldMemberExpression *node)
+{
+ accept(node->base);
+ out << "." << Engine::toString(node->name);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FieldMemberExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NewMemberExpression *node)
+{
+ out << "new ";
+ accept(node->base);
+ out << "(";
+ accept(node->arguments);
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NewMemberExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NewExpression *node)
+{
+ Q_UNUSED(node);
+ out << "new ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::NewExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CallExpression *node)
+{
+ accept(node->base);
+ out << "(";
+ accept(node->arguments);
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CallExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ArgumentList *node)
+{
+ accept(node->expression);
+ for (node = node->next; node != 0; node = node->next) {
+ out << ", ";
+ accept(node->expression);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ArgumentList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PostIncrementExpression *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PostIncrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "++";
+}
+
+bool PrettyPretty::visit(AST::PostDecrementExpression *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PostDecrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "--";
+}
+
+bool PrettyPretty::visit(AST::DeleteExpression *node)
+{
+ Q_UNUSED(node);
+ out << "delete ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::DeleteExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::VoidExpression *node)
+{
+ Q_UNUSED(node);
+ out << "void ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::VoidExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TypeOfExpression *node)
+{
+ Q_UNUSED(node);
+ out << "typeof ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::TypeOfExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PreIncrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "++";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PreIncrementExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PreDecrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "--";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PreDecrementExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::UnaryPlusExpression *node)
+{
+ out << "+";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::UnaryPlusExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::UnaryMinusExpression *node)
+{
+ out << "-";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::UnaryMinusExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TildeExpression *node)
+{
+ out << "~";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::TildeExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NotExpression *node)
+{
+ out << "!";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NotExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::BinaryExpression *node)
+{
+ bool needParens = node->left->binaryExpressionCast()
+ && (compareOperatorPrecedence(node->left->binaryExpressionCast()->op, node->op) < 0);
+ if (needParens)
+ out << "(";
+ accept(node->left);
+ if (needParens)
+ out << ")";
+ QString s;
+ switch (node->op) {
+ case QSOperator::Add:
+ s = QLatin1String("+"); break;
+ case QSOperator::And:
+ s = QLatin1String("&&"); break;
+ case QSOperator::InplaceAnd:
+ s = QLatin1String("&="); break;
+ case QSOperator::Assign:
+ s = QLatin1String("="); break;
+ case QSOperator::BitAnd:
+ s = QLatin1String("&"); break;
+ case QSOperator::BitOr:
+ s = QLatin1String("|"); break;
+ case QSOperator::BitXor:
+ s = QLatin1String("^"); break;
+ case QSOperator::InplaceSub:
+ s = QLatin1String("-="); break;
+ case QSOperator::Div:
+ s = QLatin1String("/"); break;
+ case QSOperator::InplaceDiv:
+ s = QLatin1String("/="); break;
+ case QSOperator::Equal:
+ s = QLatin1String("=="); break;
+ case QSOperator::Ge:
+ s = QLatin1String(">="); break;
+ case QSOperator::Gt:
+ s = QLatin1String(">"); break;
+ case QSOperator::In:
+ s = QLatin1String("in"); break;
+ case QSOperator::InplaceAdd:
+ s = QLatin1String("+="); break;
+ case QSOperator::InstanceOf:
+ s = QLatin1String("instanceof"); break;
+ case QSOperator::Le:
+ s = QLatin1String("<="); break;
+ case QSOperator::LShift:
+ s = QLatin1String("<<"); break;
+ case QSOperator::InplaceLeftShift:
+ s = QLatin1String("<<="); break;
+ case QSOperator::Lt:
+ s = QLatin1String("<"); break;
+ case QSOperator::Mod:
+ s = QLatin1String("%"); break;
+ case QSOperator::InplaceMod:
+ s = QLatin1String("%="); break;
+ case QSOperator::Mul:
+ s = QLatin1String("*"); break;
+ case QSOperator::InplaceMul:
+ s = QLatin1String("*="); break;
+ case QSOperator::NotEqual:
+ s = QLatin1String("!="); break;
+ case QSOperator::Or:
+ s = QLatin1String("||"); break;
+ case QSOperator::InplaceOr:
+ s = QLatin1String("|="); break;
+ case QSOperator::RShift:
+ s = QLatin1String(">>"); break;
+ case QSOperator::InplaceRightShift:
+ s = QLatin1String(">>="); break;
+ case QSOperator::StrictEqual:
+ s = QLatin1String("==="); break;
+ case QSOperator::StrictNotEqual:
+ s = QLatin1String("!=="); break;
+ case QSOperator::Sub:
+ s = QLatin1String("-"); break;
+ case QSOperator::URShift:
+ s = QLatin1String(">>>"); break;
+ case QSOperator::InplaceURightShift:
+ s = QLatin1String(">>>="); break;
+ case QSOperator::InplaceXor:
+ s = QLatin1String("^="); break;
+ default:
+ Q_ASSERT (0);
+ }
+ out << " " << s << " ";
+ needParens = node->right->binaryExpressionCast()
+ && (compareOperatorPrecedence(node->right->binaryExpressionCast()->op, node->op) <= 0);
+ if (needParens)
+ out << "(";
+ accept(node->right);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::BinaryExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ConditionalExpression *node)
+{
+ accept(node->expression);
+ out << " ? ";
+ accept(node->ok);
+ out << " : ";
+ accept(node->ko);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ConditionalExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Expression *node)
+{
+ accept(node->left);
+ out << ", ";
+ accept(node->right);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::Expression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Block *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Block *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StatementList *node)
+{
+ accept(node->statement);
+ for (node = node->next; node != 0; node = node->next) {
+ newlineAndIndent();
+ accept(node->statement);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::StatementList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::VariableDeclarationList *node)
+{
+ AST::VariableDeclarationList *it = node;
+
+ do {
+ it->declaration->accept(this);
+ it = it->next;
+ if (it)
+ out << ", ";
+ } while (it);
+
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::VariableDeclarationList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::VariableStatement *node)
+{
+ out << "var ";
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::VariableStatement *node)
+{
+ Q_UNUSED(node);
+ out << ";";
+}
+
+bool PrettyPretty::visit(AST::VariableDeclaration *node)
+{
+ out << Engine::toString(node->name);
+ if (node->expression) {
+ out << " = ";
+ accept(node->expression);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::VariableDeclaration *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::EmptyStatement *node)
+{
+ Q_UNUSED(node);
+ out << ";";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::EmptyStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ExpressionStatement *node)
+{
+ accept(node->expression);
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ExpressionStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::IfStatement *node)
+{
+ out << "if (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->ok);
+ if (node->ko) {
+ out << " else ";
+ acceptAsBlock(node->ko);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::IfStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::DoWhileStatement *node)
+{
+ out << "do ";
+ acceptAsBlock(node->statement);
+ out << " while (";
+ accept(node->expression);
+ out << ");";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::DoWhileStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::WhileStatement *node)
+{
+ out << "while (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::WhileStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ForStatement *node)
+{
+ out << "for (";
+ accept(node->initialiser);
+ out << "; ";
+ accept(node->condition);
+ out << "; ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ForStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::LocalForStatement *node)
+{
+ out << "for (var ";
+ accept(node->declarations);
+ out << "; ";
+ accept(node->condition);
+ out << "; ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::LocalForStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ForEachStatement *node)
+{
+ out << "for (";
+ accept(node->initialiser);
+ out << " in ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ForEachStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::LocalForEachStatement *node)
+{
+ out << "for (var ";
+ accept(node->declaration);
+ out << " in ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::LocalForEachStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ContinueStatement *node)
+{
+ out << "continue";
+ if (node->label) {
+ out << " " << Engine::toString(node->label);
+ }
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ContinueStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::BreakStatement *node)
+{
+ out << "break";
+ if (node->label) {
+ out << " " << Engine::toString(node->label);
+ }
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::BreakStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ReturnStatement *node)
+{
+ out << "return";
+ if (node->expression) {
+ out << " ";
+ accept(node->expression);
+ }
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ReturnStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::WithStatement *node)
+{
+ out << "with (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::WithStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::SwitchStatement *node)
+{
+ out << "switch (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->block);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::SwitchStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CaseBlock *node)
+{
+ accept(node->clauses);
+ if (node->defaultClause) {
+ newlineAndIndent();
+ accept(node->defaultClause);
+ }
+ if (node->moreClauses) {
+ newlineAndIndent();
+ accept(node->moreClauses);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CaseBlock *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CaseClauses *node)
+{
+ accept(node->clause);
+ for (node = node->next; node != 0; node = node->next) {
+ newlineAndIndent();
+ accept(node->clause);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CaseClauses *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CaseClause *node)
+{
+ out << "case ";
+ accept(node->expression);
+ out << ":";
+ if (node->statements) {
+ newlineAndIndent();
+ accept(node->statements);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CaseClause *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::DefaultClause *node)
+{
+ Q_UNUSED(node);
+ out << "default:";
+ newlineAndIndent();
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::DefaultClause *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::LabelledStatement *node)
+{
+ out << Engine::toString(node->label) << ": ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::LabelledStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ThrowStatement *node)
+{
+ Q_UNUSED(node);
+ out << "throw ";
+ accept(node->expression);
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ThrowStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TryStatement *node)
+{
+ out << "try ";
+ acceptAsBlock(node->statement);
+ if (node->catchExpression) {
+ out << " catch (" << Engine::toString(node->catchExpression->name) << ") ";
+ acceptAsBlock(node->catchExpression->statement);
+ }
+ if (node->finallyExpression) {
+ out << " finally ";
+ acceptAsBlock(node->finallyExpression->statement);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::TryStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Catch *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Catch *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Finally *node)
+{
+ Q_UNUSED(node);
+ out << "finally ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Finally *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionDeclaration *node)
+{
+ out << "function";
+
+ if (node->name)
+ out << " " << Engine::toString(node->name);
+
+ // the arguments
+ out << "(";
+ for (AST::FormalParameterList *it = node->formals; it; it = it->next) {
+ if (it->name)
+ out << Engine::toString(it->name);
+
+ if (it->next)
+ out << ", ";
+ }
+ out << ")";
+
+ // the function body
+ out << " {";
+
+ if (node->body) {
+ pushIndentLevel();
+ newlineAndIndent();
+ accept(node->body);
+ popIndentLevel();
+ newlineAndIndent();
+ }
+
+ out << "}";
+
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FunctionDeclaration *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionExpression *node)
+{
+ out << "function";
+
+ if (node->name)
+ out << " " << Engine::toString(node->name);
+
+ // the arguments
+ out << "(";
+ for (AST::FormalParameterList *it = node->formals; it; it = it->next) {
+ if (it->name)
+ out << Engine::toString(it->name);
+
+ if (it->next)
+ out << ", ";
+ }
+ out << ")";
+
+ // the function body
+ out << " {";
+
+ if (node->body) {
+ pushIndentLevel();
+ newlineAndIndent();
+ accept(node->body);
+ popIndentLevel();
+ newlineAndIndent();
+ }
+
+ out << "}";
+
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FunctionExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FormalParameterList *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::FormalParameterList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionBody *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::FunctionBody *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Program *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Program *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::SourceElements *node)
+{
+ Q_UNUSED(node);
+ accept(node->element);
+ for (node = node->next; node != 0; node = node->next) {
+ newlineAndIndent();
+ accept(node->element);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::SourceElements *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionSourceElement *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::FunctionSourceElement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StatementSourceElement *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::StatementSourceElement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::DebuggerStatement *node)
+{
+ Q_UNUSED(node);
+ out << "debugger";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::DebuggerStatement *node)
+{
+ Q_UNUSED(node);
+ out << ";";
+}
+
+bool PrettyPretty::preVisit(AST::Node *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptprettypretty_p.h b/src/declarative/qml/parser/javascriptprettypretty_p.h
new file mode 100644
index 0000000..c692da5
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptprettypretty_p.h
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTPRETTYPRETTY_P_H
+#define JAVASCRIPTPRETTYPRETTY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTextStream;
+
+namespace JavaScript {
+
+class PrettyPretty: protected AST::Visitor
+{
+public:
+ PrettyPretty(QTextStream &out);
+ virtual ~PrettyPretty();
+
+ QTextStream &operator () (AST::Node *node, int level = 0);
+
+protected:
+ void accept(AST::Node *node);
+
+ virtual bool preVisit(AST::Node *node);
+
+ virtual bool visit(AST::ThisExpression *node);
+ virtual void endVisit(AST::ThisExpression *node);
+
+ virtual bool visit(AST::IdentifierExpression *node);
+ virtual void endVisit(AST::IdentifierExpression *node);
+
+ virtual bool visit(AST::NullExpression *node);
+ virtual void endVisit(AST::NullExpression *node);
+
+ virtual bool visit(AST::TrueLiteral *node);
+ virtual void endVisit(AST::TrueLiteral *node);
+
+ virtual bool visit(AST::FalseLiteral *node);
+ virtual void endVisit(AST::FalseLiteral *node);
+
+ virtual bool visit(AST::StringLiteral *node);
+ virtual void endVisit(AST::StringLiteral *node);
+
+ virtual bool visit(AST::NumericLiteral *node);
+ virtual void endVisit(AST::NumericLiteral *node);
+
+ virtual bool visit(AST::RegExpLiteral *node);
+ virtual void endVisit(AST::RegExpLiteral *node);
+
+ virtual bool visit(AST::ArrayLiteral *node);
+ virtual void endVisit(AST::ArrayLiteral *node);
+
+ virtual bool visit(AST::ObjectLiteral *node);
+ virtual void endVisit(AST::ObjectLiteral *node);
+
+ virtual bool visit(AST::ElementList *node);
+ virtual void endVisit(AST::ElementList *node);
+
+ virtual bool visit(AST::Elision *node);
+ virtual void endVisit(AST::Elision *node);
+
+ virtual bool visit(AST::PropertyNameAndValueList *node);
+ virtual void endVisit(AST::PropertyNameAndValueList *node);
+
+ virtual bool visit(AST::IdentifierPropertyName *node);
+ virtual void endVisit(AST::IdentifierPropertyName *node);
+
+ virtual bool visit(AST::StringLiteralPropertyName *node);
+ virtual void endVisit(AST::StringLiteralPropertyName *node);
+
+ virtual bool visit(AST::NumericLiteralPropertyName *node);
+ virtual void endVisit(AST::NumericLiteralPropertyName *node);
+
+ virtual bool visit(AST::ArrayMemberExpression *node);
+ virtual void endVisit(AST::ArrayMemberExpression *node);
+
+ virtual bool visit(AST::FieldMemberExpression *node);
+ virtual void endVisit(AST::FieldMemberExpression *node);
+
+ virtual bool visit(AST::NewMemberExpression *node);
+ virtual void endVisit(AST::NewMemberExpression *node);
+
+ virtual bool visit(AST::NewExpression *node);
+ virtual void endVisit(AST::NewExpression *node);
+
+ virtual bool visit(AST::CallExpression *node);
+ virtual void endVisit(AST::CallExpression *node);
+
+ virtual bool visit(AST::ArgumentList *node);
+ virtual void endVisit(AST::ArgumentList *node);
+
+ virtual bool visit(AST::PostIncrementExpression *node);
+ virtual void endVisit(AST::PostIncrementExpression *node);
+
+ virtual bool visit(AST::PostDecrementExpression *node);
+ virtual void endVisit(AST::PostDecrementExpression *node);
+
+ virtual bool visit(AST::DeleteExpression *node);
+ virtual void endVisit(AST::DeleteExpression *node);
+
+ virtual bool visit(AST::VoidExpression *node);
+ virtual void endVisit(AST::VoidExpression *node);
+
+ virtual bool visit(AST::TypeOfExpression *node);
+ virtual void endVisit(AST::TypeOfExpression *node);
+
+ virtual bool visit(AST::PreIncrementExpression *node);
+ virtual void endVisit(AST::PreIncrementExpression *node);
+
+ virtual bool visit(AST::PreDecrementExpression *node);
+ virtual void endVisit(AST::PreDecrementExpression *node);
+
+ virtual bool visit(AST::UnaryPlusExpression *node);
+ virtual void endVisit(AST::UnaryPlusExpression *node);
+
+ virtual bool visit(AST::UnaryMinusExpression *node);
+ virtual void endVisit(AST::UnaryMinusExpression *node);
+
+ virtual bool visit(AST::TildeExpression *node);
+ virtual void endVisit(AST::TildeExpression *node);
+
+ virtual bool visit(AST::NotExpression *node);
+ virtual void endVisit(AST::NotExpression *node);
+
+ virtual bool visit(AST::BinaryExpression *node);
+ virtual void endVisit(AST::BinaryExpression *node);
+
+ virtual bool visit(AST::ConditionalExpression *node);
+ virtual void endVisit(AST::ConditionalExpression *node);
+
+ virtual bool visit(AST::Expression *node);
+ virtual void endVisit(AST::Expression *node);
+
+ virtual bool visit(AST::Block *node);
+ virtual void endVisit(AST::Block *node);
+
+ virtual bool visit(AST::StatementList *node);
+ virtual void endVisit(AST::StatementList *node);
+
+ virtual bool visit(AST::VariableStatement *node);
+ virtual void endVisit(AST::VariableStatement *node);
+
+ virtual bool visit(AST::VariableDeclarationList *node);
+ virtual void endVisit(AST::VariableDeclarationList *node);
+
+ virtual bool visit(AST::VariableDeclaration *node);
+ virtual void endVisit(AST::VariableDeclaration *node);
+
+ virtual bool visit(AST::EmptyStatement *node);
+ virtual void endVisit(AST::EmptyStatement *node);
+
+ virtual bool visit(AST::ExpressionStatement *node);
+ virtual void endVisit(AST::ExpressionStatement *node);
+
+ virtual bool visit(AST::IfStatement *node);
+ virtual void endVisit(AST::IfStatement *node);
+
+ virtual bool visit(AST::DoWhileStatement *node);
+ virtual void endVisit(AST::DoWhileStatement *node);
+
+ virtual bool visit(AST::WhileStatement *node);
+ virtual void endVisit(AST::WhileStatement *node);
+
+ virtual bool visit(AST::ForStatement *node);
+ virtual void endVisit(AST::ForStatement *node);
+
+ virtual bool visit(AST::LocalForStatement *node);
+ virtual void endVisit(AST::LocalForStatement *node);
+
+ virtual bool visit(AST::ForEachStatement *node);
+ virtual void endVisit(AST::ForEachStatement *node);
+
+ virtual bool visit(AST::LocalForEachStatement *node);
+ virtual void endVisit(AST::LocalForEachStatement *node);
+
+ virtual bool visit(AST::ContinueStatement *node);
+ virtual void endVisit(AST::ContinueStatement *node);
+
+ virtual bool visit(AST::BreakStatement *node);
+ virtual void endVisit(AST::BreakStatement *node);
+
+ virtual bool visit(AST::ReturnStatement *node);
+ virtual void endVisit(AST::ReturnStatement *node);
+
+ virtual bool visit(AST::WithStatement *node);
+ virtual void endVisit(AST::WithStatement *node);
+
+ virtual bool visit(AST::SwitchStatement *node);
+ virtual void endVisit(AST::SwitchStatement *node);
+
+ virtual bool visit(AST::CaseBlock *node);
+ virtual void endVisit(AST::CaseBlock *node);
+
+ virtual bool visit(AST::CaseClauses *node);
+ virtual void endVisit(AST::CaseClauses *node);
+
+ virtual bool visit(AST::CaseClause *node);
+ virtual void endVisit(AST::CaseClause *node);
+
+ virtual bool visit(AST::DefaultClause *node);
+ virtual void endVisit(AST::DefaultClause *node);
+
+ virtual bool visit(AST::LabelledStatement *node);
+ virtual void endVisit(AST::LabelledStatement *node);
+
+ virtual bool visit(AST::ThrowStatement *node);
+ virtual void endVisit(AST::ThrowStatement *node);
+
+ virtual bool visit(AST::TryStatement *node);
+ virtual void endVisit(AST::TryStatement *node);
+
+ virtual bool visit(AST::Catch *node);
+ virtual void endVisit(AST::Catch *node);
+
+ virtual bool visit(AST::Finally *node);
+ virtual void endVisit(AST::Finally *node);
+
+ virtual bool visit(AST::FunctionDeclaration *node);
+ virtual void endVisit(AST::FunctionDeclaration *node);
+
+ virtual bool visit(AST::FunctionExpression *node);
+ virtual void endVisit(AST::FunctionExpression *node);
+
+ virtual bool visit(AST::FormalParameterList *node);
+ virtual void endVisit(AST::FormalParameterList *node);
+
+ virtual bool visit(AST::FunctionBody *node);
+ virtual void endVisit(AST::FunctionBody *node);
+
+ virtual bool visit(AST::Program *node);
+ virtual void endVisit(AST::Program *node);
+
+ virtual bool visit(AST::SourceElements *node);
+ virtual void endVisit(AST::SourceElements *node);
+
+ virtual bool visit(AST::FunctionSourceElement *node);
+ virtual void endVisit(AST::FunctionSourceElement *node);
+
+ virtual bool visit(AST::StatementSourceElement *node);
+ virtual void endVisit(AST::StatementSourceElement *node);
+
+ virtual bool visit(AST::DebuggerStatement *node);
+ virtual void endVisit(AST::DebuggerStatement *node);
+
+ int indentLevel(int level)
+ {
+ int was = m_indentLevel;
+ m_indentLevel = level;
+ return was;
+ }
+
+ void pushIndentLevel()
+ { ++m_indentLevel; }
+
+ void popIndentLevel()
+ { --m_indentLevel; }
+
+ QTextStream &newlineAndIndent();
+
+ void acceptAsBlock(AST::Node *node);
+
+ static int operatorPrecedenceLevel(int op);
+ static int compareOperatorPrecedence(int op1, int op2);
+
+private:
+ QTextStream &out;
+ int m_indentLevel;
+
+ Q_DISABLE_COPY(PrettyPretty)
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/parser.pri b/src/declarative/qml/parser/parser.pri
new file mode 100644
index 0000000..72bd46c
--- /dev/null
+++ b/src/declarative/qml/parser/parser.pri
@@ -0,0 +1,22 @@
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/javascriptast_p.h \
+ $$PWD/javascriptastfwd_p.h \
+ $$PWD/javascriptastvisitor_p.h \
+ $$PWD/javascriptengine_p.h \
+ $$PWD/javascriptgrammar_p.h \
+ $$PWD/javascriptlexer_p.h \
+ $$PWD/javascriptmemorypool_p.h \
+ $$PWD/javascriptnodepool_p.h \
+ $$PWD/javascriptparser_p.h \
+ $$PWD/javascriptprettypretty_p.h
+
+SOURCES += $$PWD/javascriptast.cpp \
+ $$PWD/javascriptastvisitor.cpp \
+ $$PWD/javascriptengine_p.cpp \
+ $$PWD/javascriptgrammar.cpp \
+ $$PWD/javascriptlexer.cpp \
+ $$PWD/javascriptprettypretty.cpp \
+ $$PWD/javascriptparser.cpp
+
diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h
new file mode 100644
index 0000000..370bb58
--- /dev/null
+++ b/src/declarative/qml/qml.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QML_H
+#define QML_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qmetaobject.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtDeclarative/qmlparserstatus.h>
+#include <QtDeclarative/qmllist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+#define QML_DECLARE_TYPE(TYPE) \
+ Q_DECLARE_METATYPE(TYPE *) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *) \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *)
+
+#define QML_DECLARE_TYPE_HASMETATYPE(TYPE) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *) \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *)
+
+#define QML_DECLARE_INTERFACE(INTERFACE) \
+ QML_DECLARE_TYPE(INTERFACE)
+
+#define QML_DECLARE_INTERFACE_HASMETATYPE(INTERFACE) \
+ QML_DECLARE_TYPE_HASMETATYPE(INTERFACE)
+
+#define QML_DEFINE_INTERFACE(INTERFACE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<INTERFACE *>::instance(qmlRegisterInterface<INTERFACE>(#INTERFACE));
+
+#define QML_DEFINE_EXTENDED_TYPE(TYPE, NAME, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#NAME, #TYPE));
+
+#define QML_DEFINE_TYPE(TYPE, NAME) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(#NAME, #TYPE));
+
+#define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE));
+
+#define QML_DEFINE_NOCREATE_TYPE(TYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(#TYPE));
+
+class QmlContext;
+class QmlEngine;
+Q_DECLARATIVE_EXPORT QmlContext *qmlContext(const QObject *);
+Q_DECLARATIVE_EXPORT QmlEngine *qmlEngine(const QObject *);
+Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *);
+
+template<typename T>
+QObject *qmlAttachedPropertiesObject(const QObject *obj)
+{
+ // ### is this threadsafe?
+ static int idx = -1;
+
+ if (idx == -1)
+ idx = QmlMetaType::attachedPropertiesFuncId(&T::staticMetaObject);
+
+ if (idx == -1 || !obj)
+ return 0;
+
+ return qmlAttachedPropertiesObjectById(idx, obj);
+}
+
+QML_DECLARE_TYPE(QObject)
+Q_DECLARE_METATYPE(QVariant)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QML_H
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
new file mode 100644
index 0000000..c61200e
--- /dev/null
+++ b/src/declarative/qml/qml.pri
@@ -0,0 +1,74 @@
+SOURCES += qml/qmlparser.cpp \
+ qml/qmlinstruction.cpp \
+ qml/qmlvmemetaobject.cpp \
+ qml/qmlengine.cpp \
+ qml/qmlbindablevalue.cpp \
+ qml/qmlmetaproperty.cpp \
+ qml/qmlcomponent.cpp \
+ qml/qmlcontext.cpp \
+ qml/qmlcustomparser.cpp \
+ qml/qmlpropertyvaluesource.cpp \
+ qml/qmlproxymetaobject.cpp \
+ qml/qmlvme.cpp \
+ qml/qmlcompiler.cpp \
+ qml/qmlcompiledcomponent.cpp \
+ qml/qmlboundsignal.cpp \
+ qml/qmldom.cpp \
+ qml/qmlrefcount.cpp \
+ qml/qmlprivate.cpp \
+ qml/qmlmetatype.cpp \
+ qml/qmlstringconverters.cpp \
+ qml/qmlclassfactory.cpp \
+ qml/qmlparserstatus.cpp \
+ qml/qmlcompositetypemanager.cpp \
+ qml/qmlinfo.cpp \
+ qml/qmlerror.cpp \
+ qml/qmlscriptparser.cpp \
+ qml/qmlbasicscript.cpp
+
+HEADERS += qml/qmlparser_p.h \
+ qml/qmlinstruction_p.h \
+ qml/qmlvmemetaobject_p.h \
+ qml/qml.h \
+ qml/qmlbindablevalue.h \
+ qml/qmlbindablevalue_p.h \
+ qml/qmlmetaproperty.h \
+ qml/qmlcomponent.h \
+ qml/qmlcomponent_p.h \
+ qml/qmlcustomparser_p.h \
+ qml/qmlcustomparser_p_p.h \
+ qml/qmlpropertyvaluesource.h \
+ qml/qmlboundsignal_p.h \
+ qml/qmlparserstatus.h \
+ qml/qmlproxymetaobject_p.h \
+ qml/qmlcompiledcomponent_p.h \
+ qml/qmlvme_p.h \
+ qml/qmlcompiler_p.h \
+ qml/qmlengine_p.h \
+ qml/qmlprivate.h \
+ qml/qmldom.h \
+ qml/qmldom_p.h \
+ qml/qmlrefcount_p.h \
+ qml/qmlmetatype.h \
+ qml/qmlengine.h \
+ qml/qmlcontext.h \
+ qml/qmlexpression.h \
+ qml/qmlstringconverters_p.h \
+ qml/qmlclassfactory_p.h \
+ qml/qmlinfo.h \
+ qml/qmlmetaproperty_p.h \
+ qml/qmlcontext_p.h \
+ qml/qmlcompositetypemanager_p.h \
+ qml/qmllist.h \
+ qml/qmldeclarativedata_p.h \
+ qml/qmlerror.h \
+ qml/qmlscriptparser_p.h \
+ qml/qmlbasicscript_p.h
+
+# for qtscript debugger
+QT += scripttools
+
+include(script/script.pri)
+include(parser/parser.pri)
+include(rewriter/rewriter.pri)
+
diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp
new file mode 100644
index 0000000..3d74b37
--- /dev/null
+++ b/src/declarative/qml/qmlbasicscript.cpp
@@ -0,0 +1,853 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlbasicscript_p.h"
+#include <QColor>
+#include <QDebug>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <QStack>
+#include <qfxperf.h>
+#include <private/qmlrefcount_p.h>
+#include <private/javascriptast_p.h>
+#include <private/javascriptengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ScriptInstruction {
+ enum {
+ Load, // fetch
+ Fetch, // fetch
+
+ Add, // NA
+ Subtract, // NA
+ Multiply, // NA
+ Equals, // NA
+ And, // NA
+
+ Int, // integer
+ Bool, // boolean
+ } type;
+
+ union {
+ struct {
+ int idx;
+ } fetch;
+ struct {
+ int value;
+ } integer;
+ struct {
+ bool value;
+ } boolean;
+ };
+};
+
+DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
+
+class QmlBasicScriptPrivate
+{
+public:
+ enum Flags { OwnData = 0x00000001 };
+
+ int size;
+ int stateSize;
+ int instructionCount;
+ int exprLen;
+
+ ScriptInstruction *instructions() const { return (ScriptInstruction *)((char *)this + sizeof(QmlBasicScriptPrivate)); }
+
+ const char *expr() const
+ {
+ return (const char *)(instructions() + instructionCount);
+ }
+
+ const char *data() const
+ {
+ return (const char *)(instructions() + instructionCount) + exprLen + 1;
+ }
+
+ static unsigned int alignRound(int s)
+ {
+ if (s % 4)
+ s += 4 - (s % 4);
+ return s;
+ }
+};
+
+QDebug operator<<(QDebug lhs, const QmlBasicScriptNodeCache &rhs)
+{
+ switch(rhs.type) {
+ case QmlBasicScriptNodeCache::Invalid:
+ lhs << "Invalid";
+ break;
+ case QmlBasicScriptNodeCache::Core:
+ lhs << "Core" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::Attached:
+ lhs << "Attached" << rhs.object << rhs.attached;
+ break;
+ case QmlBasicScriptNodeCache::Signal:
+ lhs << "Signal" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::SignalProperty:
+ lhs << "SignalProperty" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::Variant:
+ lhs << "Variant" << rhs.context;
+ break;
+ }
+
+ return lhs;
+}
+
+void QmlBasicScriptNodeCache::clear()
+{
+ object = 0;
+ metaObject = 0;
+ type = Invalid;
+}
+
+static QVariant toObjectOrVariant(const QVariant &v)
+{
+ switch(v.type()) {
+ case QVariant::String:
+ case QVariant::UInt:
+ case QVariant::Int:
+ case 135:
+ case QVariant::Double:
+ case QVariant::Color:
+ case QVariant::Bool:
+ default:
+ return v;
+ case QVariant::UserType:
+ {
+ QObject *o = QmlMetaType::toQObject(v);
+ if (o)
+ return qVariantFromValue(o);
+ else
+ return v;
+ }
+ break;
+ }
+}
+
+static QVariant fetch_value(QObject *o, int idx, int type)
+{
+ switch(type) {
+ case QVariant::String:
+ {
+ QString val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::UInt:
+ {
+ uint val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Int:
+ {
+ int val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case 135:
+ {
+ float val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Double:
+ {
+ double val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ default:
+ {
+ if (QmlMetaType::isObject(type)) {
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *val = 0;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant::fromValue(val);
+ } else {
+ QVariant var = o->metaObject()->property(idx).read(o);
+ if (QmlMetaType::isObject(var.userType())) {
+ QObject *obj = 0;
+ obj = *(QObject **)var.data();
+ var = QVariant::fromValue(obj);
+ }
+ return var;
+ }
+ }
+ break;
+ };
+}
+
+QVariant QmlBasicScriptNodeCache::value(const char *) const
+{
+ //QFxPerfTimer<QFxPerf::BasicScriptValue> pt;
+ switch(type) {
+ case Invalid:
+ break;
+ case Core:
+ return fetch_value(object, core, coreType);
+ break;
+ case Attached:
+ return qVariantFromValue(static_cast<QObject *>(attached));
+ break;
+ case Signal:
+ // XXX
+ Q_ASSERT(!"Not implemented");
+ break;
+ case SignalProperty:
+ break;
+ case Variant:
+ return context->propertyValues[contextIndex];
+ };
+ return QVariant();
+}
+
+struct QmlBasicScriptCompiler
+{
+ QmlBasicScriptCompiler()
+ : script(0), stateSize(0) {}
+ QmlBasicScript *script;
+ int stateSize;
+
+ bool compile(JavaScript::AST::Node *);
+
+ bool compileExpression(JavaScript::AST::Node *);
+
+ bool tryConstant(JavaScript::AST::Node *);
+ bool parseConstant(JavaScript::AST::Node *);
+ bool tryName(JavaScript::AST::Node *);
+ bool parseName(JavaScript::AST::Node *);
+ bool tryBinaryExpression(JavaScript::AST::Node *);
+ bool compileBinaryExpression(JavaScript::AST::Node *);
+
+ QByteArray data;
+ QList<ScriptInstruction> bytecode;
+};
+
+/*!
+ \internal
+ \class QmlBasicScript
+ \brief The QmlBasicScript class provides a fast implementation of a limited subset of JavaScript bindings.
+
+ QmlBasicScript instances are used to accelerate binding. Instead of using
+ the slower, fully fledged JavaScript engine, many simple bindings can be
+ evaluated using the QmlBasicScript engine.
+
+ To see if the QmlBasicScript engine can handle a binding, call compile()
+ and check the return value, or isValid() afterwards.
+
+ To evaluate the binding, the QmlBasicScript instance needs some memory in
+ which to cache state. This may be allocated by calling newScriptState()
+ and destroyed by calling deleteScriptState(). The state data is then passed
+ to the run() method when evaluating the binding.
+
+ To further accelerate binding, QmlBasicScript can return a precompiled
+ version of itself that can be saved for future use. Call compileData() to
+ get an opaque pointer to the compiled state, and compileDataSize() for the
+ size of this data in bytes. This data can be saved and passed to future
+ instances of the QmlBasicScript constructor. The initial copy of compile
+ data is owned by the QmlBindScript instance on which compile() was called.
+*/
+
+/*!
+ Create a new QmlBasicScript instance.
+*/
+QmlBasicScript::QmlBasicScript()
+: flags(0), d(0), rc(0)
+{
+}
+
+/*!
+ Create a new QmlBasicScript instance from saved \a data.
+
+ \a data \b must be data previously acquired from calling compileData() on a
+ previously created QmlBasicScript instance. Any other data will almost
+ certainly cause the QmlBasicScript engine to crash.
+
+ \a data must continue to be valid throughout the QmlBasicScript instance
+ life. It does not assume ownership of the memory.
+
+ If \a owner is set, it is referenced on creation and dereferenced on
+ destruction of this instance.
+*/
+QmlBasicScript::QmlBasicScript(const char *data, QmlRefCount *owner)
+: flags(0), d((QmlBasicScriptPrivate *)data), rc(owner)
+{
+ if (rc) rc->addref();
+}
+
+/*!
+ Return the text of the script expression.
+ */
+QByteArray QmlBasicScript::expression() const
+{
+ if (!d)
+ return QByteArray();
+ else
+ return QByteArray(d->expr());
+}
+
+/*!
+ Destroy the script instance.
+*/
+QmlBasicScript::~QmlBasicScript()
+{
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ if (rc) rc->release();
+ d = 0;
+ rc = 0;
+}
+
+/*!
+ Clear this script. The object will then be in its initial state, as though
+ it were freshly constructed with default constructor.
+*/
+void QmlBasicScript::clear()
+{
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ if (rc) rc->release();
+ d = 0;
+ rc = 0;
+ flags = 0;
+}
+
+/*!
+ Return the script state memory for this script instance. This memory should
+ only be destroyed by calling deleteScriptState().
+ */
+void *QmlBasicScript::newScriptState()
+{
+ if (!d) {
+ return 0;
+ } else {
+ void *rv = ::malloc(d->stateSize * sizeof(QmlBasicScriptNodeCache));
+ ::memset(rv, 0, d->stateSize * sizeof(QmlBasicScriptNodeCache));
+ return rv;
+ }
+}
+
+/*!
+ Delete the \a data previously allocated by newScriptState().
+ */
+void QmlBasicScript::deleteScriptState(void *data)
+{
+ if (!data) return;
+ Q_ASSERT(d);
+ clearCache(data);
+ free(data);
+}
+
+/*!
+ Dump the script instructions to stderr for debugging.
+ */
+void QmlBasicScript::dump()
+{
+ if (!d)
+ return;
+
+ qWarning() << d->instructionCount << "instructions:";
+ const char *data = d->data();
+ for (int ii = 0; ii < d->instructionCount; ++ii) {
+ const ScriptInstruction &instr = d->instructions()[ii];
+
+ switch(instr.type) {
+ case ScriptInstruction::Load:
+ qWarning().nospace() << "LOAD\t\t" << instr.fetch.idx << "\t\t"
+ << QByteArray(data + instr.fetch.idx);
+ break;
+ case ScriptInstruction::Fetch:
+ qWarning().nospace() << "FETCH\t\t" << instr.fetch.idx << "\t\t"
+ << QByteArray(data + instr.fetch.idx);
+ break;
+ case ScriptInstruction::Add:
+ qWarning().nospace() << "ADD";
+ break;
+ case ScriptInstruction::Subtract:
+ qWarning().nospace() << "SUBTRACT";
+ break;
+ case ScriptInstruction::Multiply:
+ qWarning().nospace() << "MULTIPLY";
+ break;
+ case ScriptInstruction::Equals:
+ qWarning().nospace() << "EQUALS";
+ break;
+ case ScriptInstruction::Int:
+ qWarning().nospace() << "INT\t\t" << instr.integer.value;
+ break;
+ case ScriptInstruction::Bool:
+ qWarning().nospace() << "BOOL\t\t" << instr.boolean.value;
+ break;
+ default:
+ qWarning().nospace() << "UNKNOWN";
+ break;
+ }
+ }
+}
+
+/*!
+ Return true if this is a valid script binding, otherwise returns false.
+ */
+bool QmlBasicScript::isValid() const
+{
+ return d != 0;
+}
+
+/*!
+ Compile \a v and return true if the compilation is successful, otherwise
+ returns false.
+ */
+bool QmlBasicScript::compile(const QmlParser::Variant &v)
+{
+ if (!v.asAST()) return false;
+
+ QByteArray expr = v.asScript().toLatin1();
+ const char *src = expr.constData();
+
+ QmlBasicScriptCompiler bsc;
+ bsc.script = this;
+
+ if (d) {
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ d = 0;
+ flags = 0;
+ }
+
+ if (bsc.compile(v.asAST())) {
+ int len = ::strlen(src);
+ flags = QmlBasicScriptPrivate::OwnData;
+ int size = sizeof(QmlBasicScriptPrivate) +
+ bsc.bytecode.count() * sizeof(ScriptInstruction) +
+ QmlBasicScriptPrivate::alignRound(bsc.data.count() + len + 1);
+ d = (QmlBasicScriptPrivate *) malloc(size);
+ d->size = size;
+ d->stateSize = bsc.stateSize;
+ d->instructionCount = bsc.bytecode.count();
+ d->exprLen = len;
+ ::memcpy((char *)d->expr(), src, len + 1);
+ for (int ii = 0; ii < d->instructionCount; ++ii)
+ d->instructions()[ii] = bsc.bytecode.at(ii);
+ ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count());
+ }
+
+ return d != 0;
+}
+
+bool QmlBasicScriptCompiler::compile(JavaScript::AST::Node *node)
+{
+ return compileExpression(node);
+}
+
+using namespace JavaScript;
+bool QmlBasicScriptCompiler::tryConstant(JavaScript::AST::Node *node)
+{
+ if (node->kind == AST::Node::Kind_TrueLiteral ||
+ node->kind == AST::Node::Kind_FalseLiteral)
+ return true;
+
+ if (node->kind == AST::Node::Kind_NumericLiteral) {
+ AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node);
+
+ return lit->suffix == AST::NumericLiteral::noSuffix &&
+ double(int(lit->value)) == lit->value;
+ }
+
+ return false;
+}
+
+bool QmlBasicScriptCompiler::parseConstant(JavaScript::AST::Node *node)
+{
+ ScriptInstruction instr;
+
+ if (node->kind == AST::Node::Kind_NumericLiteral) {
+ AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node);
+ instr.type = ScriptInstruction::Int;
+ instr.integer.value = int(lit->value);
+ } else {
+ instr.type = ScriptInstruction::Bool;
+ instr.boolean.value = node->kind == AST::Node::Kind_TrueLiteral;
+ }
+
+ bytecode.append(instr);
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::tryName(JavaScript::AST::Node *node)
+{
+ return node->kind == AST::Node::Kind_IdentifierExpression ||
+ node->kind == AST::Node::Kind_FieldMemberExpression;
+}
+
+bool QmlBasicScriptCompiler::parseName(AST::Node *node)
+{
+ bool load = false;
+
+ QString name;
+ if (node->kind == AST::Node::Kind_IdentifierExpression) {
+ name = static_cast<AST::IdentifierExpression *>(node)->name->asString();
+ load = true;
+ } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
+ AST::FieldMemberExpression *expr = static_cast<AST::FieldMemberExpression *>(node);
+
+ if (!parseName(expr->base))
+ return false;
+
+ name = expr->name->asString();
+ } else {
+ return false;
+ }
+
+ int nref = data.count();
+ data.append(name.toUtf8());
+ data.append('\0');
+ ScriptInstruction instr;
+ if (load)
+ instr.type = ScriptInstruction::Load;
+ else
+ instr.type = ScriptInstruction::Fetch;
+ instr.fetch.idx = nref;
+ bytecode.append(instr);
+ ++stateSize;
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::compileExpression(JavaScript::AST::Node *node)
+{
+ if (tryBinaryExpression(node))
+ return compileBinaryExpression(node);
+ else if (tryConstant(node))
+ return parseConstant(node);
+ else if (tryName(node))
+ return parseName(node);
+ else
+ return false;
+}
+
+bool QmlBasicScriptCompiler::tryBinaryExpression(AST::Node *node)
+{
+ if (node->kind == AST::Node::Kind_BinaryExpression) {
+ AST::BinaryExpression *expr =
+ static_cast<AST::BinaryExpression *>(node);
+
+ if (expr->op == QSOperator::Add ||
+ expr->op == QSOperator::Sub ||
+ expr->op == QSOperator::Equal ||
+ expr->op == QSOperator::And ||
+ expr->op == QSOperator::Mul)
+ return true;
+ }
+ return false;
+}
+
+bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node)
+{
+ if (node->kind == AST::Node::Kind_BinaryExpression) {
+ AST::BinaryExpression *expr =
+ static_cast<AST::BinaryExpression *>(node);
+
+ if (!compileExpression(expr->left)) return false;
+ if (!compileExpression(expr->right)) return false;
+
+ ScriptInstruction instr;
+ switch (expr->op) {
+ case QSOperator::Add:
+ instr.type = ScriptInstruction::Add;
+ break;
+ case QSOperator::Sub:
+ instr.type = ScriptInstruction::Subtract;
+ break;
+ case QSOperator::Equal:
+ instr.type = ScriptInstruction::Equals;
+ break;
+ case QSOperator::And:
+ instr.type = ScriptInstruction::And;
+ break;
+ case QSOperator::Mul:
+ instr.type = ScriptInstruction::Multiply;
+ break;
+ default:
+ return false;
+ }
+
+ bytecode.append(instr);
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \internal
+*/
+void QmlBasicScript::clearCache(void *voidCache)
+{
+ QmlBasicScriptNodeCache *dataCache =
+ reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
+
+ for (int ii = 0; ii < d->stateSize; ++ii) {
+ if (!dataCache[ii].isCore() && !dataCache[ii].isVariant() &&
+ dataCache[ii].object) {
+ QMetaObject::removeGuard(&dataCache[ii].object);
+ dataCache[ii].object = 0;
+ }
+ dataCache[ii].clear();
+ }
+}
+
+void QmlBasicScript::guard(QmlBasicScriptNodeCache &n)
+{
+ if (n.object) {
+ if (n.isVariant()) {
+ } else if (n.isCore()) {
+ n.metaObject =
+ n.object->metaObject();
+ } else {
+ QMetaObject::addGuard(&n.object);
+ }
+ }
+}
+
+bool QmlBasicScript::valid(QmlBasicScriptNodeCache &n, QObject *obj)
+{
+ return n.object == obj &&
+ (!n.isCore() || obj->metaObject() == n.metaObject);
+}
+
+
+/*!
+ \enum QmlBasicScript::CacheState
+ \value NoChange The query has not change. Any previous monitoring is still
+ valid.
+ \value Incremental The query has been incrementally changed. Any previous
+ monitoring is still valid, but needs to have the fresh properties added to
+ it.
+ \value Reset The entire query has been reset from the beginning. Any previous
+ monitoring is now invalid.
+*/
+
+/*!
+ Run the script in \a context and return the result. \a voidCache should
+ contain state memory previously acquired from newScript.
+ */
+QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *cached)
+{
+ if (!isValid())
+ return QVariant();
+
+ QmlBasicScriptNodeCache *dataCache =
+ reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
+ int dataCacheItem;
+ QStack<QVariant> stack;
+
+ bool resetting = false;
+ bool hasReset = false;
+
+ const char *data = d->data();
+
+ if (dataCache[0].type == QmlBasicScriptNodeCache::Invalid) {
+ resetting = true;
+ hasReset = true;
+ }
+
+ CacheState state = NoChange;
+
+ dataCacheItem = 0;
+ for (int idx = 0; idx < d->instructionCount; ++idx) {
+ const ScriptInstruction &instr = d->instructions()[idx];
+
+ switch(instr.type) {
+ case ScriptInstruction::Load: // either an object or a property
+ case ScriptInstruction::Fetch: // can only be a property
+ {
+ const char *id = data + instr.fetch.idx;
+ QmlBasicScriptNodeCache &n = dataCache[dataCacheItem];
+
+ if (instr.type == ScriptInstruction::Load) {
+
+ if (n.type == QmlBasicScriptNodeCache::Invalid) {
+ context->engine()->d_func()->loadCache(n, QLatin1String(id), static_cast<QmlContextPrivate*>(context->d_ptr));
+ state = Incremental;
+ }
+
+ if(!n.isValid())
+ qWarning("ReferenceError: %s is not defined", id);
+
+ } else { // instr.type == ScriptInstruction::Fetch
+
+ QVariant o = stack.pop();
+ QObject *obj = qvariant_cast<QObject *>(o);
+ if (!obj) {
+ if (n.type == QmlBasicScriptNodeCache::Invalid) {
+ if (scriptWarnings())
+ qWarning() << "QmlBasicScript: Unable to convert" << o;
+ *cached = state;
+ return QVariant();
+ } else {
+ clearCache(dataCache);
+ *cached = Reset;
+ CacheState dummy;
+ return run(context, voidCache, &dummy);
+ }
+ } else if (n.type == QmlBasicScriptNodeCache::Invalid) {
+ context->engine()->d_func()->fetchCache(n, QLatin1String(id), obj);
+ guard(n);
+ state = Incremental;
+ } else if (!valid(n, obj)) {
+ clearCache(dataCache);
+ *cached = Reset;
+ CacheState dummy;
+ return run(context, voidCache, &dummy);
+ }
+
+ }
+
+ QVariant var = n.value(id);
+ stack.push(var);
+ ++dataCacheItem;
+ }
+ break;
+ case ScriptInstruction::Int:
+ stack.push(QVariant(instr.integer.value));
+ break;
+ case ScriptInstruction::Bool:
+ stack.push(QVariant(instr.boolean.value));
+ break;
+ case ScriptInstruction::Add:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toDouble() + lhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Subtract:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(lhs.toDouble() - rhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Multiply:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toDouble() * lhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Equals:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs == lhs);
+ }
+ break;
+ case ScriptInstruction::And:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toBool() && lhs.toBool());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ *cached = state;
+
+ if (stack.isEmpty())
+ return QVariant();
+ else
+ return stack.top();
+}
+
+/*!
+ Return a pointer to the script's compile data, or null if there is no data.
+ */
+const char *QmlBasicScript::compileData() const
+{
+ return (const char *)d;
+}
+
+/*!
+ Return the size of the script's compile data, or zero if there is no data.
+ The size will always be a multiple of 4.
+ */
+unsigned int QmlBasicScript::compileDataSize() const
+{
+ if (d)
+ return d->size;
+ else
+ return 0;
+}
+
+bool QmlBasicScript::isSingleLoad() const
+{
+ if (!d)
+ return false;
+
+ return d->instructionCount == 1 &&
+ d->instructions()[0].type == ScriptInstruction::Load;
+}
+
+QByteArray QmlBasicScript::singleLoadTarget() const
+{
+ if (!isSingleLoad())
+ return QByteArray();
+
+ // We know there is one instruction and it is a load
+ return QByteArray(d->data() + d->instructions()[0].fetch.idx);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h
new file mode 100644
index 0000000..1117e11
--- /dev/null
+++ b/src/declarative/qml/qmlbasicscript_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBASICSCRIPT_P_H
+#define QMLBASICSCRIPT_P_H
+
+#include <QtCore/QList>
+#include <QtCore/QByteArray>
+#include <QtCore/QVariant>
+#include <private/qmlparser_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QmlRefCount;
+class QmlContext;
+class QmlBasicScriptPrivate;
+class QmlBasicScriptNodeCache;
+class QmlBasicScript
+{
+public:
+ QmlBasicScript();
+ QmlBasicScript(const char *, QmlRefCount * = 0);
+ ~QmlBasicScript();
+
+ // Always 4-byte aligned
+ const char *compileData() const;
+ unsigned int compileDataSize() const;
+
+ QByteArray expression() const;
+
+ bool compile(const QmlParser::Variant &);
+ bool isValid() const;
+
+ void clear();
+
+ void dump();
+ void *newScriptState();
+ void deleteScriptState(void *);
+
+ enum CacheState { NoChange, Incremental, Reset };
+ QVariant run(QmlContext *, void *, CacheState *);
+
+ // Optimization opportunities
+ bool isSingleLoad() const;
+ QByteArray singleLoadTarget() const;
+
+private:
+ int flags;
+ QmlBasicScriptPrivate *d;
+ QmlRefCount *rc;
+
+ void clearCache(void *);
+ void guard(QmlBasicScriptNodeCache &);
+ bool valid(QmlBasicScriptNodeCache &, QObject *);
+};
+
+class QmlContextPrivate;
+class QDebug;
+class QmlBasicScriptNodeCache
+{
+public:
+ QObject *object;
+ const QMetaObject *metaObject;
+ enum { Invalid,
+ Core,
+ Attached,
+ Signal,
+ SignalProperty,
+ Variant
+ } type;
+ union {
+ int core;
+ QObject *attached;
+ QmlContextPrivate *context;
+ };
+ int coreType;
+ int contextIndex;
+
+ bool isValid() const { return type != Invalid; }
+ bool isCore() const { return type == Core; }
+ bool isVariant() const { return type == Variant; }
+ void clear();
+ QVariant value(const char *) const;
+};
+
+QDebug operator<<(QDebug, const QmlBasicScriptNodeCache &);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLBASICSCRIPT_P_H
+
+
diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp
new file mode 100644
index 0000000..351e0bd
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qml.h>
+#include "qmlbindablevalue.h"
+#include "qmlbindablevalue_p.h"
+#include <qmlcontext.h>
+#include <qmlinfo.h>
+#include <QVariant>
+#include <qfxperf.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
+
+QmlBindableValuePrivate::QmlBindableValuePrivate()
+: inited(false), updating(false), mePtr(0)
+{
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlBindableValue);
+QmlBindableValue::QmlBindableValue(QObject *parent)
+: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent)
+{
+ qFatal("QmlBindableValue: Default constructor not supported");
+}
+
+QmlBindableValue::QmlBindableValue(void *data, QmlRefCount *rc, QObject *obj, QObject *parent)
+: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(QmlContext::activeContext(), data, rc, obj)
+{
+}
+
+QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, QObject *parent)
+: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(QmlContext::activeContext(), str, obj)
+{
+}
+
+QmlBindableValue::~QmlBindableValue()
+{
+ Q_D(QmlBindableValue);
+ if(d->mePtr)
+ *(d->mePtr) = 0;
+}
+
+void QmlBindableValue::setTarget(const QmlMetaProperty &prop)
+{
+ Q_D(QmlBindableValue);
+ d->property = prop;
+
+ update();
+}
+
+QmlMetaProperty QmlBindableValue::property() const
+{
+ Q_D(const QmlBindableValue);
+ return d->property;
+}
+
+void QmlBindableValue::init()
+{
+ Q_D(QmlBindableValue);
+
+ if (d->inited)
+ return;
+ d->inited = true;
+ update();
+}
+
+void QmlBindableValue::setExpression(const QString &expr)
+{
+ QmlExpression::setExpression(expr);
+ update();
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void QmlBindableValue::update()
+{
+ Q_D(QmlBindableValue);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
+#endif
+ if (!d->inited)
+ return;
+
+ if (!d->updating) {
+ d->updating = true;
+
+ if (d->property.propertyCategory() == QmlMetaProperty::List) {
+ QVariant value = this->value();
+ int listType = QmlMetaType::listType(d->property.propertyType());
+
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = d->property.read();
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (value.type() == uint(listType) ||
+ value.userType() == listType) {
+ QVariant listVar = d->property.read();
+ QmlMetaType::clear(listVar);
+ QmlMetaType::append(listVar, value);
+ }
+ } else if (d->property.propertyCategory() == QmlMetaProperty::QmlList) {
+ // XXX - optimize!
+ QVariant value = this->value();
+ QVariant list = d->property.read();
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if (d->property.propertyCategory() == QmlMetaProperty::Bindable) {
+
+ // NOTE: We assume that only core properties can have
+ // propertyType == Bindable
+ int idx = d->property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+ void *a[1];
+ QmlBindableValue *t = this;
+ a[0] = (void *)&t;
+ d->property.object()->qt_metacall(QMetaObject::WriteProperty,
+ idx, a);
+
+ } else if (d->property.propertyCategory() == QmlMetaProperty::Object) {
+
+ QVariant value = this->value();
+ if ((int)value.type() != qMetaTypeId<QObject *>()) {
+ if (scriptWarnings()) {
+ if (!value.isValid()) {
+ qWarning() << "QmlBindableValue: Unable to assign invalid value to object property";
+ } else {
+ qWarning() << "QmlBindableValue: Unable to assign non-object to object property";
+ }
+ }
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *obj = *(QObject **)value.data();
+
+ // NOTE: We assume that only core properties can have
+ // propertyType == Object
+ int idx = d->property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+ void *a[1];
+ a[0] = (void *)&obj;
+ d->property.object()->qt_metacall(QMetaObject::WriteProperty,
+ idx, a);
+
+ } else if (d->property.propertyCategory() == QmlMetaProperty::Normal) {
+ QVariant value = this->value();
+ d->property.write(value);
+ }
+
+ d->updating = false;
+ } else {
+ qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name();
+ }
+}
+
+void QmlBindableValue::valueChanged()
+{
+ update();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbindablevalue.h b/src/declarative/qml/qmlbindablevalue.h
new file mode 100644
index 0000000..71a7051
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBINDABLEVALUE_H
+#define QMLBINDABLEVALUE_H
+
+#include <QtCore/QObject>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlexpression.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlExpression;
+class QmlContext;
+class QmlBindableValuePrivate;
+class Q_DECLARATIVE_EXPORT QmlBindableValue : public QmlPropertyValueSource,
+ public QmlExpression
+{
+Q_OBJECT
+public:
+ QmlBindableValue(QObject *parent);
+ QmlBindableValue(const QString &, QObject *, QObject *parent=0);
+ QmlBindableValue(void *, QmlRefCount *, QObject *, QObject *parent);
+ ~QmlBindableValue();
+
+ virtual void setTarget(const QmlMetaProperty &);
+ QmlMetaProperty property() const;
+
+ Q_CLASSINFO("DefaultProperty", "expression")
+ Q_PROPERTY(QString expression READ expression WRITE setExpression)
+ virtual void setExpression(const QString &);
+
+ void init();
+
+private Q_SLOTS:
+ void update();
+
+protected:
+ virtual void valueChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QmlBindableValue)
+};
+QML_DECLARE_TYPE(QmlBindableValue)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLBINDABLEVALUE_H
diff --git a/src/declarative/qml/qmlbindablevalue_p.h b/src/declarative/qml/qmlbindablevalue_p.h
new file mode 100644
index 0000000..9476b80
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBINDABLEVALUE_P_H
+#define QMLBINDABLEVALUE_P_H
+
+#include <private/qobject_p.h>
+#include <QtDeclarative/qmlbindablevalue.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlBindableValuePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlBindableValue)
+public:
+ QmlBindableValuePrivate();
+
+ bool inited;
+ bool updating;
+ QmlMetaProperty property;
+
+ QmlBindableValue **mePtr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLBINDABLEVALUE_P_H
diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp
new file mode 100644
index 0000000..5815dc6
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlboundsignal_p.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include "private/qmlengine_p.h"
+#include "private/qmlcontext_p.h"
+#include <qfxglobal.h>
+#include <qmlmetatype.h>
+#include <qml.h>
+#include <qmlcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+int QmlBoundSignal::evaluateIdx = -1;
+QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
+: QmlExpressionObject(ctxt, val, me, false), _idx(idx)
+{
+ // A cached evaluation of the QmlExpressionObject::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if (evaluateIdx == -1) evaluateIdx = QmlExpressionObject::staticMetaObject.indexOfMethod("value()");
+
+ setTrackChange(false);
+ QFx_setParent_noEvent(this, parent);
+ QMetaObject::connect(me, _idx, this, evaluateIdx);
+}
+
+QmlBoundSignalProxy::QmlBoundSignalProxy(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
+: QmlBoundSignal(ctxt, val, me, idx, parent)
+{
+ QMetaMethod signal = me->metaObject()->method(idx);
+
+ params = new QmlBoundSignalParameters(signal, this);
+
+ ctxt->d_func()->addDefaultObject(params, QmlContextPrivate::HighPriority);
+}
+
+int QmlBoundSignalProxy::qt_metacall(QMetaObject::Call c, int id, void **a)
+{
+ if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
+ params->setValues(a);
+ value();
+ params->clearValues();
+ return -1;
+ } else {
+ return QmlBoundSignal::qt_metacall(c, id, a);
+ }
+}
+
+#include <QDebug>
+QmlBoundSignalParameters::QmlBoundSignalParameters(const QMetaMethod &method,
+ QObject *parent)
+: QObject(parent), types(0), values(0)
+{
+ MetaObject *mo = new MetaObject(this);
+
+ // ### Optimize!
+ // ### Ensure only supported types are allowed, otherwise it might crash
+ QMetaObjectBuilder mob;
+ mob.setSuperClass(&QmlBoundSignalParameters::staticMetaObject);
+ mob.setClassName("QmlBoundSignalParameters");
+
+ QList<QByteArray> paramTypes = method.parameterTypes();
+ QList<QByteArray> paramNames = method.parameterNames();
+ types = new int[paramTypes.count()];
+ for (int ii = 0; ii < paramTypes.count(); ++ii) {
+ const QByteArray &type = paramTypes.at(ii);
+ const QByteArray &name = paramNames.at(ii);
+
+ if (name.isEmpty() || type.isEmpty()) {
+ types[ii] = 0;
+ continue;
+ }
+
+ QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
+ if (QmlMetaType::isObject(t)) {
+ types[ii] = QMetaType::QObjectStar;
+ QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
+ prop.setWritable(false);
+ } else {
+ types[ii] = t;
+ QMetaPropertyBuilder prop = mob.addProperty(name, type);
+ prop.setWritable(false);
+ }
+ }
+ myMetaObject = mob.toMetaObject();
+ *static_cast<QMetaObject *>(mo) = *myMetaObject;
+
+ d_ptr->metaObject = mo;
+}
+
+QmlBoundSignalParameters::~QmlBoundSignalParameters()
+{
+ delete [] types;
+ qFree(myMetaObject);
+}
+
+void QmlBoundSignalParameters::setValues(void **v)
+{
+ values = v;
+}
+
+void QmlBoundSignalParameters::clearValues()
+{
+ values = 0;
+}
+
+int QmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (c == QMetaObject::ReadProperty && id >= 1) {
+ QmlMetaType::copy(types[id - 1], a[0], values[id]);
+ return -1;
+ } else {
+ return qt_metacall(c, id, a);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h
new file mode 100644
index 0000000..2c05770
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBOUNDSIGNAL_P_H
+#define QMLBOUNDSIGNAL_P_H
+
+#include <QtDeclarative/qmlexpression.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+class QmlBoundSignal : public QmlExpressionObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignal(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
+
+ int index() const { return _idx; }
+protected:
+ static int evaluateIdx;
+private:
+ int _idx;
+};
+
+class QmlBoundSignalParameters : public QObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
+ ~QmlBoundSignalParameters();
+
+ void setValues(void **);
+ void clearValues();
+
+private:
+ friend class MetaObject;
+ int metaCall(QMetaObject::Call, int _id, void **);
+ struct MetaObject : public QAbstractDynamicMetaObject {
+ MetaObject(QmlBoundSignalParameters *b)
+ : parent(b) {}
+
+ int metaCall(QMetaObject::Call c, int id, void **a) {
+ return parent->metaCall(c, id, a);
+ }
+ QmlBoundSignalParameters *parent;
+ };
+
+ int *types;
+ void **values;
+ QMetaObject *myMetaObject;
+};
+
+class QmlBoundSignalProxy : public QmlBoundSignal
+{
+public:
+ QmlBoundSignalProxy(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
+
+protected:
+ virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
+private:
+ QmlBoundSignalParameters *params;
+};
+
+
+#endif // QMLBOUNDSIGNAL_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlclassfactory.cpp b/src/declarative/qml/qmlclassfactory.cpp
new file mode 100644
index 0000000..7e5b929
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlclassfactory_p.h"
+
+QmlClassFactory::~QmlClassFactory()
+{
+}
+
diff --git a/src/declarative/qml/qmlclassfactory_p.h b/src/declarative/qml/qmlclassfactory_p.h
new file mode 100644
index 0000000..e3e71c9
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCLASSFACTORY_P_H
+#define QMLCLASSFACTORY_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QByteArray;
+class QUrl;
+class QmlComponent;
+
+class QmlClassFactory
+{
+public:
+ virtual ~QmlClassFactory();
+ virtual QmlComponent *create(const QByteArray &, const QUrl& baseUrl, QmlEngine*) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCLASSFACTORY_P_H
diff --git a/src/declarative/qml/qmlcompiledcomponent.cpp b/src/declarative/qml/qmlcompiledcomponent.cpp
new file mode 100644
index 0000000..bea736a
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledcomponent.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcompiledcomponent_p.h"
+#include "qmlparser_p.h"
+#include <QtCore/qdebug.h>
+#include <QmlComponent>
+using namespace QmlParser;
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
+
+QmlCompiledComponent::QmlCompiledComponent()
+: dumpStatus(NoDump)
+{
+}
+
+QmlCompiledComponent::~QmlCompiledComponent()
+{
+ for (int ii = 0; ii < synthesizedMetaObjects.count(); ++ii)
+ qFree(synthesizedMetaObjects.at(ii));
+}
+
+
+void QmlCompiledComponent::dumpInstructions()
+{
+ if (!compilerDump())
+ return;
+
+ if (!name.isEmpty())
+ qWarning() << name;
+ qWarning() << "Index\tLine\tOperation\t\tData1\tData2\t\tComments";
+ qWarning() << "-------------------------------------------------------------------------------";
+ for (int ii = 0; ii < bytecode.count(); ++ii) {
+ dump(&bytecode[ii], ii);
+ }
+ qWarning() << "-------------------------------------------------------------------------------";
+}
+
+void QmlCompiledComponent::dumpPre()
+{
+ if (!(dumpStatus & DumpPre)) {
+ dumpInstructions();
+ dumpStatus = (DumpStatus)(dumpStatus | DumpPre);
+ }
+}
+
+void QmlCompiledComponent::dumpPost()
+{
+ if (!(dumpStatus & DumpPost)) {
+ dumpInstructions();
+ dumpStatus = (DumpStatus)(dumpStatus | DumpPost);
+ }
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiledcomponent_p.h b/src/declarative/qml/qmlcompiledcomponent_p.h
new file mode 100644
index 0000000..2201423
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledcomponent_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPILEDCOMPONENT_P_H
+#define QMLCOMPILEDCOMPONENT_P_H
+
+#include <QtDeclarative/qml.h>
+#include <private/qmlinstruction_p.h>
+#include <private/qmlcompiler_p.h>
+#include <private/qmlrefcount_p.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+namespace QmlParser {
+ class Property;
+ class Object;
+ class Value;
+};
+
+class QmlCompiledComponent : public QmlRefCount, public QmlCompiledData
+{
+public:
+ QmlCompiledComponent();
+ ~QmlCompiledComponent();
+
+ void dumpPre();
+ void dumpPost();
+
+private:
+ enum DumpStatus { NoDump = 0x00, DumpPre = 0x01, DumpPost = 0x02 } dumpStatus;
+ void dumpInstructions();
+ void dump(QmlInstruction *, int idx = -1);
+ friend class QmlCompiler;
+ friend class QmlDomDocument;
+};
+
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QMLCOMPILEDCOMPONENT_P_H
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
new file mode 100644
index 0000000..46695b7
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -0,0 +1,1618 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qmlcompiler_p.h"
+#include <qfxperf.h>
+#include "qmlparser_p.h"
+#include "private/qmlscriptparser_p.h"
+#include <qmlpropertyvaluesource.h>
+#include <qmlcomponent.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include "qmlbasicscript_p.h"
+#include <QColor>
+#include <QDebug>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <private/qmlcompiledcomponent_p.h>
+#include <private/qmlstringconverters_p.h>
+#include <private/qmlengine_p.h>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlmetatype.h>
+#include <QtCore/qdebug.h>
+#include "private/qmlcustomparser_p_p.h"
+#include <private/qmlcontext_p.h>
+#include <private/qmlcomponent_p.h>
+#include "parser/javascriptast_p.h"
+
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+int QmlCompiledData::indexForString(const QString &data)
+{
+ int idx = primitives.indexOf(data);
+ if (idx == -1) {
+ idx = primitives.count();
+ primitives << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForByteArray(const QByteArray &data)
+{
+ int idx = datas.indexOf(data);
+ if (idx == -1) {
+ idx = datas.count();
+ datas << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForFloat(float *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= floatData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (floatData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = floatData.count();
+ for (int ii = 0; ii < count; ++ii)
+ floatData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForInt(int *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= intData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (intData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = intData.count();
+ for (int ii = 0; ii < count; ++ii)
+ intData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::Location &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l;
+ return rv;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l.start << l.end;
+ return rv;
+}
+
+QmlCompiler::QmlCompiler()
+: output(0)
+{
+}
+
+bool QmlCompiler::isError() const
+{
+ return !exceptions.isEmpty();
+}
+
+QList<QmlError> QmlCompiler::errors() const
+{
+ return exceptions;
+}
+
+bool QmlCompiler::isValidId(const QString &val)
+{
+ if (val.isEmpty())
+ return false;
+
+ QChar u(QLatin1Char('_'));
+ for (int ii = 0; ii < val.count(); ++ii)
+ if (val.at(ii) != u &&
+ ((ii == 0 && !val.at(ii).isLetter()) ||
+ (ii != 0 && !val.at(ii).isLetterOrNumber())) )
+ return false;
+
+ return true;
+}
+
+/*!
+ Returns true if \a name refers to an attached property, false otherwise.
+
+ Attached property names are those that start with a capital letter.
+*/
+bool QmlCompiler::isAttachedPropertyName(const QByteArray &name)
+{
+ return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z';
+}
+
+/*!
+ Returns true if \a name refers to a signal property, false otherwise.
+
+ Signal property names are those that start with "on", followed by a capital
+ letter.
+*/
+bool QmlCompiler::isSignalPropertyName(const QByteArray &name)
+{
+ return name.length() >= 3 && name.startsWith("on") &&
+ 'A' <= name.at(2) && 'Z' >= name.at(2);
+}
+
+#define COMPILE_EXCEPTION2(token, desc) \
+ { \
+ QString exceptionDescription; \
+ QmlError error; \
+ error.setUrl(output->url); \
+ error.setLine(token->location.start.line); \
+ error.setColumn(token->location.start.column); \
+ QDebug d(&exceptionDescription); \
+ d << desc; \
+ error.setDescription(exceptionDescription.trimmed()); \
+ exceptions << error; \
+ return false; \
+ }
+
+#define COMPILE_EXCEPTION(desc) \
+ { \
+ QString exceptionDescription; \
+ QmlError error; \
+ error.setUrl(output->url); \
+ error.setLine(obj->location.start.line); \
+ error.setColumn(obj->location.start.column); \
+ QDebug d(&exceptionDescription); \
+ d << desc; \
+ error.setDescription(exceptionDescription.trimmed()); \
+ exceptions << error; \
+ return false; \
+ }
+
+#define COMPILE_CHECK(a) \
+ { \
+ if (!a) return false; \
+ }
+
+// Compile a simple assignment of v to prop into instr
+bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
+ const QMetaProperty &prop,
+ QmlParser::Value *v)
+{
+ QString string = v->value.asScript();
+
+ if (!prop.isWritable())
+ COMPILE_EXCEPTION2(v, "Cannot assign literal value to read-only property" << prop.name());
+
+ if (prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string.toLatin1().constData());
+ } else
+ value = prop.enumerator().keyToValue(string.toLatin1().constData());
+ if (value == -1)
+ COMPILE_EXCEPTION2(v, "Cannot assign unknown enumeration to property" << prop.name());
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.value = value;
+ return true;
+ }
+ int type = prop.type();
+ switch(type) {
+ case -1:
+ {
+ instr.type = QmlInstruction::StoreVariant;
+ instr.storeString.propertyIndex = prop.propertyIndex();
+ instr.storeString.value = output->indexForString(string);
+ }
+ break;
+ case QVariant::String:
+ {
+ instr.type = QmlInstruction::StoreString;
+ instr.storeString.propertyIndex = prop.propertyIndex();
+ instr.storeString.value = output->indexForString(string);
+ }
+ break;
+ case QVariant::UInt:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ bool ok;
+ int value = string.toUInt(&ok);
+ if (!ok)
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to unsigned integer");
+ instr.storeInteger.value = value;
+ }
+ break;
+ case QVariant::Int:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ bool ok;
+ int value = string.toInt(&ok);
+ if (!ok)
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to integer");
+ instr.storeInteger.value = value;
+ }
+ break;
+ case 135:
+ case QVariant::Double:
+ {
+ instr.type = QmlInstruction::StoreReal;
+ instr.storeReal.propertyIndex = prop.propertyIndex();
+ bool ok;
+ float value = string.toFloat(&ok);
+ if (!ok)
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to real number");
+ instr.storeReal.value = value;
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor c = QmlStringConverters::colorFromString(string);
+ if (!c.isValid())
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to color");
+ instr.type = QmlInstruction::StoreColor;
+ instr.storeColor.propertyIndex = prop.propertyIndex();
+ instr.storeColor.value = c.rgba();
+ }
+ break;
+ case QVariant::Date:
+ {
+ QDate d = QDate::fromString(string, Qt::ISODate);
+ if (!d.isValid())
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to date");
+ instr.type = QmlInstruction::StoreDate;
+ instr.storeDate.propertyIndex = prop.propertyIndex();
+ instr.storeDate.value = d.toJulianDay();
+ }
+ break;
+ case QVariant::Time:
+ {
+ QTime time = QTime::fromString(string, Qt::ISODate);
+ if (!time.isValid())
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to time");
+ int data[] = { time.hour(), time.minute(), time.second(), time.msec() };
+ int index = output->indexForInt(data, 4);
+ instr.type = QmlInstruction::StoreTime;
+ instr.storeTime.propertyIndex = prop.propertyIndex();
+ instr.storeTime.valueIndex = index;
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
+ if (!dateTime.isValid())
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to date and time");
+ int data[] = { dateTime.date().toJulianDay(),
+ dateTime.time().hour(),
+ dateTime.time().minute(),
+ dateTime.time().second(),
+ dateTime.time().msec() };
+ int index = output->indexForInt(data, 5);
+ instr.type = QmlInstruction::StoreDateTime;
+ instr.storeDateTime.propertyIndex = prop.propertyIndex();
+ instr.storeDateTime.valueIndex = index;
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point = QmlStringConverters::pointFFromString(string, &ok);
+ if (!ok)
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to point");
+ float data[] = { point.x(), point.y() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::PointF)
+ instr.type = QmlInstruction::StorePointF;
+ else
+ instr.type = QmlInstruction::StorePoint;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
+ if (!ok)
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to size");
+ float data[] = { size.width(), size.height() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::SizeF)
+ instr.type = QmlInstruction::StoreSizeF;
+ else
+ instr.type = QmlInstruction::StoreSize;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
+ if (!ok)
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to rect");
+ float data[] = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ int index = output->indexForFloat(data, 4);
+ if (type == QVariant::RectF)
+ instr.type = QmlInstruction::StoreRectF;
+ else
+ instr.type = QmlInstruction::StoreRect;
+ instr.storeRect.propertyIndex = prop.propertyIndex();
+ instr.storeRect.valueIndex = index;
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool ok;
+ bool b = QmlStringConverters::boolFromString(string, &ok);
+ if (!ok)
+ COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to boolean");
+ instr.type = QmlInstruction::StoreBool;
+ instr.storeBool.propertyIndex = prop.propertyIndex();
+ instr.storeBool.value = b;
+ }
+ break;
+ default:
+ {
+ int t = prop.type();
+ if (t == QVariant::UserType)
+ t = prop.userType();
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(t);
+ if (converter) {
+ int index = output->customTypeData.count();
+ instr.type = QmlInstruction::AssignCustomType;
+ instr.assignCustomType.propertyIndex = prop.propertyIndex();
+ instr.assignCustomType.valueIndex = index;
+
+ QmlCompiledData::CustomTypeData data;
+ data.index = output->indexForString(string);
+ data.type = t;
+ output->customTypeData << data;
+ break;
+ }
+ }
+ COMPILE_EXCEPTION2(v, "Cannot assign to property" << prop.name() << "of unknown type" << prop.type());
+ break;
+ }
+ return true;
+}
+
+void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory)
+{
+ cc->types.clear();
+ cc->primitives.clear();
+ cc->floatData.clear();
+ cc->intData.clear();
+ cc->customTypeData.clear();
+ cc->datas.clear();
+ if (deleteMemory) {
+ for (int ii = 0; ii < cc->synthesizedMetaObjects.count(); ++ii)
+ qFree(cc->synthesizedMetaObjects.at(ii));
+ }
+ cc->synthesizedMetaObjects.clear();
+ cc->bytecode.clear();
+}
+
+bool QmlCompiler::compile(QmlEngine *engine,
+ QmlCompositeTypeData *unit,
+ QmlCompiledComponent *out)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::Compilation> pc;
+#endif
+ exceptions.clear();
+
+ Q_ASSERT(out);
+ reset(out, true);
+
+ output = out;
+
+ // Compile types
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData::TypeReference &tref = unit->types[ii];
+ QmlCompiledComponent::TypeReference ref;
+ if (tref.type)
+ ref.type = tref.type;
+ else if (tref.unit) {
+ ref.component = tref.unit->toComponent(engine);
+
+ if (ref.component->isError()) {
+ QmlError error;
+ error.setUrl(output->url);
+ error.setDescription(QLatin1String("Unable to create type ") +
+ unit->data.types().at(ii));
+ exceptions << error;
+ exceptions << ref.component->errors();
+ reset(out, true);
+ return false;
+ }
+ ref.ref = tref.unit;
+ ref.ref->addref();
+ }
+ ref.className = unit->data.types().at(ii).toLatin1();
+ out->types << ref;
+ }
+
+ Object *root = unit->data.tree();
+ Q_ASSERT(root);
+
+ compileTree(root);
+
+ if (!isError()) {
+ out->dumpPre();
+ } else {
+ reset(out, true);
+ }
+
+ output = 0;
+
+ return !isError();
+}
+
+void QmlCompiler::compileTree(Object *tree)
+{
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.line = 0;
+ init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
+ output->bytecode << init;
+
+ if (!compileObject(tree, 0)) // Compile failed
+ return;
+
+ if (tree->metatype)
+ static_cast<QMetaObject &>(output->root) = *tree->metaObject();
+ else
+ static_cast<QMetaObject &>(output->root) = *output->types.at(tree->type).metaObject();
+
+ QmlInstruction def;
+ init.line = 0;
+ def.type = QmlInstruction::SetDefault;
+ output->bytecode << def;
+
+ finalizeComponent(0);
+}
+
+bool QmlCompiler::compileObject(Object *obj, int ctxt)
+{
+ Q_ASSERT (obj->type != -1);
+ obj->metatype = output->types.at(obj->type).metaObject();
+
+ if (output->types.at(obj->type).className == "Component") {
+ COMPILE_CHECK(compileComponent(obj, ctxt));
+ return true;
+ }
+
+ ctxt = 0;
+
+ int createInstrIdx = output->bytecode.count();
+ // Create the object
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateObject;
+ create.line = obj->location.start.line;
+ create.create.data = -1;
+ create.create.type = obj->type;
+ output->bytecode << create;
+
+ // Create the synthesized meta object
+ COMPILE_CHECK(compileDynamicMeta(obj));
+
+ // Find the native type and check for the QmlParserStatus interface
+ // ### Optimize
+ const QMetaObject *mo = obj->metatype;
+ QmlType *type = 0;
+ while (!type && mo) {
+ type = QmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ Q_ASSERT(type);
+ int parserStatusCast = type->parserStatusCast();
+
+ // If the type support the QmlParserStatusInterface we need to invoke
+ // classBegin()
+ if (parserStatusCast != -1) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::BeginObject;
+ begin.begin.castValue = parserStatusCast;
+ begin.line = obj->location.start.line;
+ output->bytecode << begin;
+
+ compileState.parserStatusCount++;
+ }
+
+ // Check if this is a custom parser type. Custom parser types allow
+ // assignments to non-existant properties. These assignments are then
+ // compiled by the type.
+ bool isCustomParser = output->types.at(obj->type).type &&
+ output->types.at(obj->type).type->customParser() != 0;
+ QList<QmlCustomParserProperty> customProps;
+
+ // Compile all explicit properties specified
+ foreach(Property *prop, obj->properties) {
+
+ if (isCustomParser) {
+ // Custom parser types don't support signal properties
+ if (testProperty(prop, obj)) {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ } else {
+ if (isSignalPropertyName(prop->name)) {
+ COMPILE_CHECK(compileSignal(prop,obj));
+ } else {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ }
+ }
+
+ }
+
+ // Compile the default property
+ if (obj->defaultProperty) {
+ Property *prop = obj->defaultProperty;
+
+ if (isCustomParser) {
+ if (testProperty(prop, obj)) {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ } else {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ }
+
+ }
+
+ // Compile custom parser parts
+ if (isCustomParser && !customProps.isEmpty()) {
+ // ### Check for failure
+ bool ok = false;
+ QmlCustomParser *cp = output->types.at(obj->type).type->customParser();
+ QByteArray customData = cp->compile(customProps, &ok);
+ if(!ok)
+ COMPILE_EXCEPTION("Failure compiling custom type");
+ if(!customData.isEmpty())
+ output->bytecode[createInstrIdx].create.data =
+ output->indexForByteArray(customData);
+ }
+
+ // If the type support the QmlParserStatusInterface we need to invoke
+ // classComplete()
+ if (parserStatusCast != -1) {
+ QmlInstruction complete;
+ complete.type = QmlInstruction::CompleteObject;
+ complete.complete.castValue = parserStatusCast;
+ complete.line = obj->location.start.line;
+ output->bytecode << complete;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileComponent(Object *obj, int ctxt)
+{
+ Property *idProp = 0;
+ if (obj->properties.count() > 1 ||
+ (obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
+ COMPILE_EXCEPTION("Invalid component specification");
+ if (obj->defaultProperty &&
+ (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 ||
+ (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object)))
+ COMPILE_EXCEPTION("Invalid component body specification");
+ if (obj->properties.count())
+ idProp = *obj->properties.begin();
+ if (idProp && (idProp->value || idProp->values.count() > 1))
+ COMPILE_EXCEPTION("Invalid component id specification");
+
+ Object *root = 0;
+ if (obj->defaultProperty && obj->defaultProperty->values.count())
+ root = obj->defaultProperty->values.first()->object;
+
+ if (!root)
+ COMPILE_EXCEPTION("Cannot create empty component specification");
+
+ COMPILE_CHECK(compileComponentFromRoot(root, ctxt));
+
+ if (idProp && idProp->values.count()) {
+ QString val = idProp->values.at(0)->primitive();
+ if (!isValidId(val))
+ COMPILE_EXCEPTION("Invalid id property value");
+
+ if (compileState.ids.contains(val))
+ COMPILE_EXCEPTION("id is not unique");
+
+ IdReference reference;
+ reference.id = val;
+ reference.object = obj;
+ reference.instructionIdx = output->bytecode.count();
+ compileState.ids.insert(val, reference);
+
+ int pref = output->indexForString(val);
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = idProp->location.start.line;
+ id.setId.value = pref;
+ id.setId.save = -1;
+
+ output->bytecode << id;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
+{
+ output->bytecode.push_back(QmlInstruction());
+ QmlInstruction &create = output->bytecode.last();
+ create.type = QmlInstruction::CreateComponent;
+ create.line = obj->location.start.line;
+ create.createComponent.endLine = obj->location.end.line;
+ int count = output->bytecode.count();
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
+ init.line = obj->location.start.line;
+ output->bytecode << init;
+
+ ComponentCompileState oldComponentCompileState = compileState;
+ compileState = ComponentCompileState();
+ if (obj)
+ COMPILE_CHECK(compileObject(obj, ctxt));
+
+ finalizeComponent(count);
+ create.createComponent.count = output->bytecode.count() - count;
+ compileState = oldComponentCompileState;
+ return true;
+}
+
+
+bool QmlCompiler::compileFetchedObject(Object *obj, int ctxt)
+{
+ Q_ASSERT(obj->metatype);
+
+ if (obj->defaultProperty)
+ COMPILE_CHECK(compileProperty(obj->defaultProperty, obj, ctxt));
+
+ foreach(Property *prop, obj->properties) {
+ if (isSignalPropertyName(prop->name)) {
+ COMPILE_CHECK(compileSignal(prop, obj));
+ } else {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ }
+ }
+
+ return true;
+}
+
+int QmlCompiler::signalByName(const QMetaObject *mo, const QByteArray &name)
+{
+ int methods = mo->methodCount();
+ for (int ii = methods - 1; ii >= 0; --ii) {
+ QMetaMethod method = mo->method(ii);
+ QByteArray methodName = method.signature();
+ int idx = methodName.indexOf('(');
+ methodName = methodName.left(idx);
+
+ if (methodName == name)
+ return ii;
+ }
+ return -1;
+}
+
+bool QmlCompiler::compileSignal(Property *prop, Object *obj)
+{
+ Q_ASSERT(obj->metaObject());
+
+ if (prop->values.isEmpty() && !prop->value)
+ return true;
+
+ if (prop->value || prop->values.count() > 1)
+ COMPILE_EXCEPTION("Incorrectly specified signal");
+
+ QByteArray name = prop->name;
+ Q_ASSERT(name.startsWith("on"));
+ name = name.mid(2);
+ if(name[0] >= 'A' && name[0] <= 'Z')
+ name[0] = name[0] - 'A' + 'a';
+
+ int sigIdx = signalByName(obj->metaObject(), name);
+
+ if (sigIdx == -1) {
+
+ COMPILE_CHECK(compileProperty(prop, obj, 0));
+
+ } else {
+
+ if (prop->values.at(0)->object) {
+ int pr = output->indexForByteArray(prop->name);
+
+ bool rv = compileObject(prop->values.at(0)->object, 0);
+
+ if (rv) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignalObject;
+ assign.line = prop->values.at(0)->location.start.line;
+ assign.assignSignalObject.signal = pr;
+
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::SignalObject;
+ }
+
+ return rv;
+
+ } else {
+ QString script = prop->values.at(0)->value.asScript().trimmed();
+ if (script.isEmpty())
+ return true;
+
+ int idx = output->indexForString(script);
+
+ QmlInstruction store;
+ store.line = prop->values.at(0)->location.start.line;
+ store.type = QmlInstruction::StoreSignal;
+ store.storeSignal.signalIndex = sigIdx;
+ store.storeSignal.value = idx;
+
+ output->bytecode << store;
+
+ prop->values.at(0)->type = Value::SignalExpression;
+ }
+ }
+
+ return true;
+}
+
+// Returns true if prop exists on obj, false otherwise
+bool QmlCompiler::testProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if(isAttachedPropertyName(prop->name) || prop->name == "id")
+ return true;
+
+ const QMetaObject *mo = obj->metaObject();
+ if (mo) {
+ if (prop->isDefault) {
+ QMetaProperty p = QmlMetaType::defaultProperty(mo);
+ return p.name() != 0;
+ } else {
+ int idx = mo->indexOfProperty(prop->name.constData());
+ return idx != -1;
+ }
+ }
+
+ return false;
+}
+
+bool QmlCompiler::compileProperty(Property *prop, Object *obj, int ctxt)
+{
+ if (prop->values.isEmpty() && !prop->value)
+ COMPILE_EXCEPTION2(prop, "Empty property assignment");
+
+ const QMetaObject *metaObject = obj->metaObject();
+ Q_ASSERT(metaObject);
+
+ if (isAttachedPropertyName(prop->name)) {
+ // Setup attached property data
+ QmlType *type = QmlMetaType::qmlType(prop->name);
+
+ if (!type || !type->attachedPropertiesType())
+ COMPILE_EXCEPTION2(prop, "Non-existant attached object");
+
+ if (!prop->value)
+ COMPILE_EXCEPTION2(prop, "Cannot assign directly to attached object");
+
+ prop->value->metatype = type->attachedPropertiesType();
+ } else {
+ // Setup regular property data
+ QMetaProperty p;
+
+ if (prop->isDefault) {
+ p = QmlMetaType::defaultProperty(metaObject);
+
+ if (p.name()) {
+ prop->index = p.propertyIndex();
+ prop->name = p.name();
+ }
+
+ } else {
+ prop->index = metaObject->indexOfProperty(prop->name.constData());
+
+ if (prop->index != -1) {
+ p = metaObject->property(prop->index);
+ Q_ASSERT(p.name());
+ }
+ }
+
+ // We can't error here as the "id" property does not require a
+ // successful index resolution
+ if (p.name()) {
+ int t = p.type();
+
+ if (t == QVariant::UserType)
+ t = p.userType();
+
+ prop->type = t;
+ }
+ }
+
+ if (!prop->isDefault && prop->name == "id") {
+
+ COMPILE_CHECK(compileIdProperty(prop, obj));
+
+ } else if (isAttachedPropertyName(prop->name)) {
+
+ COMPILE_CHECK(compileAttachedProperty(prop, ctxt));
+
+ } else if (prop->index == -1) {
+
+ if (prop->isDefault) {
+ COMPILE_EXCEPTION2(prop, "Cannot assign to non-existant default property");
+ } else {
+ COMPILE_EXCEPTION2(prop, "Cannot assign to non-existant property" << prop->name);
+ }
+
+ } else if (prop->value) {
+
+ COMPILE_CHECK(compileNestedProperty(prop, ctxt));
+
+ } else if (QmlMetaType::isQmlList(prop->type) ||
+ QmlMetaType::isList(prop->type)) {
+
+ COMPILE_CHECK(compileListProperty(prop, obj, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(compilePropertyAssignment(prop, obj, ctxt));
+
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if (prop->value)
+ COMPILE_EXCEPTION2(prop,"The id property cannot be fetched");
+ if (prop->values.count() > 1)
+ COMPILE_EXCEPTION2(prop, "The object id may only be set once");
+
+ if (prop->values.at(0)->object)
+ COMPILE_EXCEPTION("Cannot assign an object as an id");
+ QString val = prop->values.at(0)->primitive();
+ if (!isValidId(val))
+ COMPILE_EXCEPTION(val << "is not a valid id");
+ if (compileState.ids.contains(val))
+ COMPILE_EXCEPTION("id is not unique");
+
+ int pref = output->indexForString(val);
+
+ if (prop->type == QVariant::String) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreString;
+ assign.storeString.propertyIndex = prop->index;
+ assign.storeString.value = pref;
+ assign.line = prop->values.at(0)->location.start.line;
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::Id;
+ } else {
+ prop->values.at(0)->type = Value::Literal;
+ }
+
+ IdReference reference;
+ reference.id = val;
+ reference.object = obj;
+ reference.instructionIdx = output->bytecode.count();
+ compileState.ids.insert(val, reference);
+
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = prop->values.at(0)->location.start.line;
+ id.setId.value = pref;
+ id.setId.save = -1;
+ output->bytecode << id;
+
+ obj->id = val.toLatin1();
+
+ return true;
+}
+
+// Compile attached property object. In this example,
+// Text {
+// GridView.row: 10
+// }
+// GridView is an attached property object.
+bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop,
+ int ctxt)
+{
+ Q_ASSERT(prop->value);
+ int id = QmlMetaType::attachedPropertiesFuncId(prop->name);
+ Q_ASSERT(id != -1); // This is checked in compileProperty()
+
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchAttached;
+ fetch.line = prop->location.start.line;
+ fetch.fetchAttached.id = id;
+ output->bytecode << fetch;
+
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+
+ return true;
+}
+
+// Compile "nested" properties. In this example:
+// Text {
+// font.size: 12
+// }
+// font is a nested property. size is not.
+bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
+ int ctxt)
+{
+ Q_ASSERT(prop->type != 0);
+ Q_ASSERT(prop->index != -1);
+
+ // Load the nested property's meta type
+ prop->value->metatype = QmlMetaType::metaObjectForType(prop->type);
+ if (!prop->value->metatype)
+ COMPILE_EXCEPTION2(prop, "Cannot nest non-QObject property" << prop->name);
+
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchObject;
+ fetch.fetch.property = prop->index;
+ fetch.fetch.isObject = true;
+ fetch.line = prop->location.start.line;
+ output->bytecode << fetch;
+
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+
+ return true;
+}
+
+// Compile assignments to QML lists. QML lists are properties of type
+// QList<T *> * and QmlList<T *> *.
+//
+// QList<T *> * types can accept a list of objects, or a single binding
+// QmlList<T *> * types can accept a list of objects
+bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ Q_ASSERT(QmlMetaType::isList(prop->type) ||
+ QmlMetaType::isQmlList(prop->type));
+
+ int t = prop->type;
+
+ if (QmlMetaType::isQmlList(t)) {
+ QmlInstruction fetch;
+ fetch.line = prop->location.start.line;
+ fetch.type = QmlInstruction::FetchQmlList;
+ fetch.fetchQmlList.property = prop->index;
+ fetch.fetchQmlList.type = QmlMetaType::qmlListType(t);
+ output->bytecode << fetch;
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = prop->location.start.line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign primitives to lists");
+ }
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopQList;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ } else {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchQList;
+ fetch.line = prop->location.start.line;
+ fetch.fetch.property = prop->index;
+ output->bytecode << fetch;
+
+ bool assignedBinding = false;
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = v->location.start.line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+ } else if (v->value.isScript()) {
+ if (assignedBinding)
+ COMPILE_EXCEPTION("Can only assign one binding to lists");
+
+ assignedBinding = true;
+ COMPILE_CHECK(compileBinding(v, prop, ctxt));
+ v->type = Value::PropertyBinding;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign primitives to lists");
+ }
+ }
+
+ QmlInstruction pop;
+ pop.line = prop->location.start.line;
+ pop.type = QmlInstruction::PopQList;
+ output->bytecode << pop;
+ }
+
+ return true;
+}
+
+// Compile regular property assignments of the form property: <value>
+//
+// ### The following problems exist
+//
+// There is no distinction between how "lists" of values are specified. This
+// Item {
+// children: Item {}
+// children: Item {}
+// }
+// is identical to
+// Item {
+// children: [ Item {}, Item {} ]
+// }
+//
+// We allow assignming multiple values to single value properties
+bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+
+ COMPILE_CHECK(compilePropertyObjectAssignment(prop, v, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(compilePropertyLiteralAssignment(prop, obj, v, ctxt));
+
+ }
+ }
+
+ return true;
+}
+
+// Compile assigning a single object instance to a regular property
+bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Value *v,
+ int ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+ Q_ASSERT(v->object->type != -1);
+
+ if (QmlMetaType::isInterface(prop->type)) {
+
+ // Assigning an object to an interface ptr property
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreInterface;
+ assign.line = v->object->location.start.line;
+ assign.storeObject.propertyIndex = prop->index;
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+
+ } else if (prop->type == -1) {
+
+ // Assigning an object to a QVariant
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreVariantObject;
+ assign.line = v->object->location.start.line;
+ assign.storeObject.propertyIndex = prop->index;
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ } else {
+ // Normally compileObject() will set this up, but we need the static
+ // meta object earlier to test for assignability. It doesn't matter
+ // that there may still be outstanding synthesized meta object changes
+ // on this type, as they are not relevant for assignability testing
+ v->object->metatype = output->types.at(v->object->type).metaObject();
+ Q_ASSERT(v->object->metaObject());
+
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions that might
+ // effect the properties on the type, but don't effect assignability
+ const QMetaObject *propertyMetaObject =
+ QmlMetaType::rawMetaObjectForType(prop->type);
+
+ // Will be true if the assigned type inherits QmlPropertyValueSource
+ bool isPropertyValue = false;
+ // Will be true if the assgned type inherits propertyMetaObject
+ bool isAssignable = false;
+ // Determine isPropertyValue and isAssignable values
+ if (propertyMetaObject) {
+ const QMetaObject *c = v->object->metatype;
+ while(c) {
+ isPropertyValue |= (c == &QmlPropertyValueSource::staticMetaObject);
+ isAssignable |= (c == propertyMetaObject);
+ c = c->superClass();
+ }
+ } else {
+ const QMetaObject *c = v->object->metatype;
+ while(!isPropertyValue && c) {
+ isPropertyValue |= (c == &QmlPropertyValueSource::staticMetaObject);
+ c = c->superClass();
+ }
+ }
+
+ if (isAssignable) {
+ // Simple assignment
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreObject;
+ assign.line = v->object->location.start.line;
+ assign.storeObject.propertyIndex = prop->index;
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ } else if (propertyMetaObject == &QmlComponent::staticMetaObject) {
+ // Automatic "Component" insertion
+ COMPILE_CHECK(compileComponentFromRoot(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreObject;
+ assign.line = v->object->location.start.line;
+ assign.storeObject.propertyIndex = prop->index;
+ output->bytecode << assign;
+
+ v->type = Value::Component;
+ } else if (isPropertyValue) {
+ // Assign as a property value source
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreValueSource;
+ assign.line = v->object->location.start.line;
+ assign.assignValueSource.property = prop->index;
+ output->bytecode << assign;
+
+ v->type = Value::ValueSource;
+ } else {
+ COMPILE_EXCEPTION2(v->object, "Unassignable object");
+ }
+ }
+
+ return true;
+}
+
+// Compile assigning a literal or binding to a regular property
+bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ int ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+
+ if (v->value.isScript()) {
+
+ COMPILE_CHECK(compileBinding(v, prop, ctxt));
+
+ v->type = Value::PropertyBinding;
+
+ } else {
+
+ QmlInstruction assign;
+ assign.line = v->location.start.line;
+ COMPILE_CHECK(compileStoreInstruction(assign, obj->metaObject()->property(prop->index), v));
+ output->bytecode << assign;
+
+ v->type = Value::Literal;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj)
+{
+ // ### FIXME - Check that there is only one default property etc.
+ if (obj->dynamicProperties.isEmpty() &&
+ obj->dynamicSignals.isEmpty() &&
+ obj->dynamicSlots.isEmpty())
+ return true;
+
+ QMetaObjectBuilder builder;
+ if (obj->metatype)
+ builder.setClassName(QByteArray(obj->metatype->className()) + "QML");
+
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (p.isDefaultProperty)
+ builder.addClassInfo("DefaultProperty", p.name);
+
+ QByteArray type;
+ switch(p.type) {
+ case Object::DynamicProperty::Variant:
+ type = "QVariant";
+ break;
+ case Object::DynamicProperty::Int:
+ type = "int";
+ break;
+ case Object::DynamicProperty::Bool:
+ type = "bool";
+ break;
+ case Object::DynamicProperty::Real:
+ type = "double";
+ break;
+ case Object::DynamicProperty::String:
+ type = "QString";
+ break;
+ case Object::DynamicProperty::Color:
+ type = "QColor";
+ break;
+ case Object::DynamicProperty::Date:
+ type = "QDate";
+ break;
+ }
+
+ builder.addSignal(p.name + "Changed()");
+ builder.addProperty(p.name, type, ii);
+ }
+
+ for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ const Object::DynamicSignal &s = obj->dynamicSignals.at(ii);
+ builder.addSignal(s.name + "()");
+ }
+
+ int slotStart = obj->dynamicSlots.isEmpty()?-1:output->primitives.count();
+
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ const Object::DynamicSlot &s = obj->dynamicSlots.at(ii);
+ builder.addSlot(s.name + "()");
+ output->primitives << s.body;
+ }
+
+ if (obj->metatype)
+ builder.setSuperClass(obj->metatype);
+
+ obj->extObjectData = builder.toMetaObject();
+ static_cast<QMetaObject &>(obj->extObject) = *obj->extObjectData;
+
+ output->synthesizedMetaObjects << obj->extObjectData;
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreMetaObject;
+ store.storeMeta.data = output->synthesizedMetaObjects.count() - 1;
+ store.storeMeta.slotData = slotStart;
+ store.line = obj->location.start.line;
+ output->bytecode << store;
+
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (p.defaultValue) {
+ p.defaultValue->name = p.name;
+ p.defaultValue->isDefault = false;
+ COMPILE_CHECK(compileProperty(p.defaultValue, obj, 0));
+ }
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileBinding(QmlParser::Value *value,
+ QmlParser::Property *prop,
+ int ctxt)
+{
+ Q_ASSERT(prop->index);
+ Q_ASSERT(prop->parent);
+ Q_ASSERT(prop->parent->metaObject());
+
+ QMetaProperty mp = prop->parent->metaObject()->property(prop->index);
+ if (!mp.isWritable() && !QmlMetaType::isList(prop->type))
+ COMPILE_EXCEPTION2(prop, "Cannot assign binding to read-only property");
+
+ BindingReference reference;
+ reference.expression = value->value;
+ reference.property = prop;
+ reference.value = value;
+ reference.instructionIdx = output->bytecode.count();
+ reference.bindingContext = ctxt;
+ compileState.bindings << reference;
+
+ output->bytecode << QmlInstruction();;
+
+ return true;
+}
+
+#if 0
+
+#include <iostream>
+#ifdef Q_CC_GNU
+#include <cxxabi.h>
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// AST Dump
+////////////////////////////////////////////////////////////////////////////////
+class Dump: protected JavaScript::AST::Visitor
+{
+ std::ostream &out;
+ int depth;
+
+public:
+ Dump(std::ostream &out)
+ : out(out), depth(-1)
+ { }
+
+ void operator()(JavaScript::AST::Node *node)
+ { JavaScript::AST::Node::acceptChild(node, this); }
+
+protected:
+ virtual bool preVisit(JavaScript::AST::Node *node)
+ {
+ const char *name = typeid(*node).name();
+#ifdef Q_CC_GNU
+ name = abi::__cxa_demangle(name, 0, 0, 0) + 17;
+#endif
+ std::cout << std::string(++depth, ' ') << name << std::endl;
+ return true;
+ }
+
+ virtual void postVisit(JavaScript::AST::Node *)
+ {
+ --depth;
+ }
+};
+#endif
+
+// Update the init instruction with final data, and optimize some simple
+// bindings
+void QmlCompiler::finalizeComponent(int patch)
+{
+ for (int ii = 0; ii < compileState.bindings.count(); ++ii) {
+ const BindingReference &binding = compileState.bindings.at(ii);
+ finalizeBinding(binding);
+ }
+
+ output->bytecode[patch].init.dataSize = compileState.savedObjects;;
+ output->bytecode[patch].init.bindingsSize = compileState.bindings.count();
+ output->bytecode[patch].init.parserStatusSize =
+ compileState.parserStatusCount;
+}
+
+void QmlCompiler::finalizeBinding(const BindingReference &binding)
+{
+ QmlBasicScript bs;
+ bs.compile(binding.expression);
+
+ QmlInstruction &instr = output->bytecode[binding.instructionIdx];
+ instr.line = binding.value->location.start.line;
+
+ // Single load optimization
+ if (bs.isValid() && bs.isSingleLoad()) {
+
+ QString singleLoadTarget = QLatin1String(bs.singleLoadTarget());
+
+ if (singleLoadTarget.at(0).isUpper() &&
+ compileState.ids.contains(singleLoadTarget) &&
+ QmlMetaType::isObject(binding.property->type)) {
+
+ IdReference reference = compileState.ids[singleLoadTarget];
+
+ const QMetaObject *idMo = reference.object->metaObject();
+ const QMetaObject *storeMo =
+ QmlMetaType::rawMetaObjectForType(binding.property->type);
+
+ Q_ASSERT(idMo);
+ Q_ASSERT(storeMo);
+
+ bool canAssign = false;
+ while (!canAssign && idMo) {
+ if (idMo == storeMo)
+ canAssign = true;
+ else
+ idMo = idMo->superClass();
+ }
+
+ if (canAssign) {
+ int instructionIdx = reference.instructionIdx;
+ if (output->bytecode.at(instructionIdx).setId.save == -1) {
+ output->bytecode[instructionIdx].setId.save =
+ compileState.savedObjects++;
+ }
+ int saveId = output->bytecode.at(instructionIdx).setId.save;
+
+ instr.type = QmlInstruction::PushProperty;
+ instr.pushProperty.property = binding.property->index;
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreStackObject;
+ store.line = 0;
+ store.assignStackObject.property =
+ compileState.pushedProperties++;
+ store.assignStackObject.object = saveId;
+ output->bytecode << store;
+ return;
+ }
+ }
+ }
+
+ // General binding fallback
+ int bref;
+ if (bs.isValid()) {
+ bref = output->indexForByteArray(QByteArray(bs.compileData(), bs.compileDataSize()));
+ } else {
+ bref = output->indexForString(binding.expression.asScript());
+ }
+
+ instr.assignBinding.context = binding.bindingContext;
+
+ if (bs.isValid())
+ instr.type = QmlInstruction::StoreCompiledBinding;
+ else
+ instr.type = QmlInstruction::StoreBinding;
+
+ instr.assignBinding.property = binding.property->index;
+ instr.assignBinding.value = bref;
+ QMetaProperty mp = binding.property->parent->metaObject()->property(binding.property->index);
+ instr.assignBinding.category = QmlMetaProperty::propertyCategory(mp);
+}
+
+QmlCompiledData::QmlCompiledData()
+{
+}
+
+QmlCompiledData::QmlCompiledData(const QmlCompiledData &other)
+{
+ *this = other;
+}
+
+QmlCompiledData::~QmlCompiledData()
+{
+ for (int ii = 0; ii < types.count(); ++ii) {
+ if (types.at(ii).ref)
+ types.at(ii).ref->release();
+ }
+}
+
+QmlCompiledData &QmlCompiledData::operator=(const QmlCompiledData &other)
+{
+ types = other.types;
+ root = other.root;
+ primitives = other.primitives;
+ floatData = other.floatData;
+ intData = other.intData;
+ customTypeData = other.customTypeData;
+ datas = other.datas;
+ synthesizedMetaObjects = other.synthesizedMetaObjects;
+ bytecode = other.bytecode;
+ return *this;
+}
+
+QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt) const
+{
+ if (type) {
+ QObject *rv = type->create();
+ if (rv)
+ QmlEngine::setContextForObject(rv, ctxt);
+ return rv;
+ } else {
+ Q_ASSERT(component);
+ QObject *rv = component->create(ctxt);
+ QmlContext *ctxt = qmlContext(rv);
+ if(ctxt) {
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(ctxt))->typeName = className;
+ }
+ return rv;
+ }
+}
+
+const QMetaObject *QmlCompiledData::TypeReference::metaObject() const
+{
+ if (type) {
+ return type->metaObject();
+ } else {
+ Q_ASSERT(component);
+ return &static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
new file mode 100644
index 0000000..6b6e1e2
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPILER_P_H
+#define QMLCOMPILER_P_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qset.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlerror.h>
+#include <private/qmlinstruction_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <private/qmlparser_p.h>
+
+class QStringList;
+
+QT_BEGIN_NAMESPACE
+class QmlEngine;
+class QmlComponent;
+class QmlCompiledComponent;
+class QmlContext;
+
+class QmlCompiledData
+{
+public:
+ QmlCompiledData();
+ QmlCompiledData(const QmlCompiledData &other);
+ QmlCompiledData &operator=(const QmlCompiledData &other);
+ virtual ~QmlCompiledData();
+
+ QByteArray name;
+ QUrl url;
+
+ struct TypeReference
+ {
+ TypeReference()
+ : type(0), component(0), ref(0) {}
+
+ QByteArray className;
+ QmlType *type;
+ QmlComponent *component;
+
+ QmlRefCount *ref;
+ QObject *createInstance(QmlContext *) const;
+ const QMetaObject *metaObject() const;
+ };
+ QList<TypeReference> types;
+ struct CustomTypeData
+ {
+ int index;
+ int type;
+ };
+ QAbstractDynamicMetaObject root;
+ QList<QString> primitives;
+ QList<float> floatData;
+ QList<int> intData;
+ QList<CustomTypeData> customTypeData;
+ QList<QByteArray> datas;
+ QList<QMetaObject *> synthesizedMetaObjects;
+ QList<QmlParser::Location> locations;
+ QList<QmlInstruction> bytecode;
+
+private:
+ friend class QmlCompiler;
+ int indexForString(const QString &);
+ int indexForByteArray(const QByteArray &);
+ int indexForFloat(float *, int);
+ int indexForInt(int *, int);
+ int indexForLocation(const QmlParser::Location &);
+ int indexForLocation(const QmlParser::LocationSpan &);
+};
+
+class Q_DECLARATIVE_EXPORT QmlCompiler
+{
+public:
+ QmlCompiler();
+
+ bool compile(QmlEngine *, QmlCompositeTypeData *, QmlCompiledComponent *);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+ static bool isValidId(const QString &);
+ static bool isAttachedPropertyName(const QByteArray &);
+ static bool isSignalPropertyName(const QByteArray &);
+
+private:
+ void reset(QmlCompiledComponent *, bool);
+
+ void compileTree(QmlParser::Object *tree);
+ bool compileObject(QmlParser::Object *obj, int);
+ bool compileComponent(QmlParser::Object *obj, int);
+ bool compileComponentFromRoot(QmlParser::Object *obj, int);
+ bool compileFetchedObject(QmlParser::Object *obj, int);
+ bool compileSignal(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool testProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ int signalByName(const QMetaObject *, const QByteArray &name);
+ bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, int);
+ bool compileIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj);
+ bool compileAttachedProperty(QmlParser::Property *prop,
+ int ctxt);
+ bool compileNestedProperty(QmlParser::Property *prop,
+ int ctxt);
+ bool compileListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compilePropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compilePropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Value *value,
+ int ctxt);
+ bool compilePropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ int ctxt);
+ bool compileStoreInstruction(QmlInstruction &instr,
+ const QMetaProperty &prop,
+ QmlParser::Value *value);
+
+ bool compileDynamicMeta(QmlParser::Object *obj);
+ bool compileBinding(QmlParser::Value *, QmlParser::Property *prop,
+ int ctxt);
+
+ void finalizeComponent(int patch);
+ struct BindingReference;
+ void finalizeBinding(const BindingReference &);
+
+ struct IdReference {
+ QString id;
+ QmlParser::Object *object;
+ int instructionIdx;
+ };
+
+ struct BindingReference {
+ QmlParser::Variant expression;
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+ int instructionIdx;
+ int bindingContext;
+ };
+
+ struct ComponentCompileState
+ {
+ ComponentCompileState() : parserStatusCount(0), savedObjects(0), pushedProperties(0) {}
+ QHash<QString, IdReference> ids;
+ int parserStatusCount;
+ int savedObjects;
+ int pushedProperties;
+ QList<BindingReference> bindings;
+ };
+ ComponentCompileState compileState;
+
+ QList<QmlError> exceptions;
+ QmlCompiledData *output;
+
+};
+
+QT_END_NAMESPACE
+#endif // QMLCOMPILER_P_H
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
new file mode 100644
index 0000000..78137e8
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -0,0 +1,547 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+#include "private/qmlcontext_p.h"
+#include "private/qmlengine_p.h"
+#include "qmlvme_p.h"
+#include "qml.h"
+#include <QStack>
+#include <qfxperf.h>
+#include <QStringList>
+#include <qmlengine.h>
+#include <QFileInfo>
+#include <qmlbindablevalue.h>
+#include "qmlcompiledcomponent_p.h"
+#include <QtCore/qdebug.h>
+#include <QApplication>
+
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+
+/*!
+ \class QmlComponent
+ \brief The QmlComponent class encapsulates a QML component description.
+ \mainclass
+*/
+
+/*!
+ \qmlclass Component QmlComponent
+ \brief The Component element encapsulates a QML component description.
+
+ Components are reusable, encapsulated Qml element with a well-defined interface.
+ They are often defined in \l {components}{Component Files}.
+
+ The \e Component element allows defining components within a QML file.
+ This can be useful for reusing a small component within a single QML
+ file, or for defining a component that logically belongs with the
+ file containing it.
+
+ \qml
+Item {
+ Component {
+ id: RedSquare
+ Rect {
+ color: "red"
+ width: 10
+ height: 10
+ }
+ }
+ ComponentInstance { component: RedSquare }
+ ComponentInstance { component: RedSquare; x: 20 }
+}
+ \endqml
+*/
+QML_DEFINE_TYPE(QmlComponent,Component);
+
+/*!
+ \enum QmlComponent::Status
+
+ Specifies the loading status of the QmlComponent.
+
+ \value Null This QmlComponent has no data. Call loadUrl() or setData() to add QML content.
+ \value Ready This QmlComponent is ready and create() may be called.
+ \value Loading This QmlComponent is loading network data.
+ \value Error An error has occured. Calling errorDescription() to retrieve a description.
+*/
+
+void QmlComponentPrivate::typeDataReady()
+{
+ Q_Q(QmlComponent);
+
+ Q_ASSERT(typeData);
+
+ fromTypeData(typeData);
+ typeData = 0;
+
+ emit q->statusChanged(q->status());
+}
+
+void QmlComponentPrivate::fromTypeData(QmlCompositeTypeData *data)
+{
+ url = QUrl(data->url);
+ QmlCompiledComponent *c = data->toCompiledComponent(engine);
+
+ if (!c) {
+ Q_ASSERT(data->status == QmlCompositeTypeData::Error);
+
+ errors = data->errors;
+
+ } else {
+
+ cc = c;
+
+ }
+
+ data->release();
+}
+
+void QmlComponentPrivate::clear()
+{
+ if (typeData) {
+ typeData->remWaiter(this);
+ typeData->release();
+ typeData = 0;
+ }
+
+ if (cc) {
+ cc->release();
+ cc = 0;
+ }
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+}
+
+/*!
+ Destruct the QmlComponent.
+*/
+QmlComponent::~QmlComponent()
+{
+ Q_D(QmlComponent);
+ if (d->typeData) {
+ d->typeData->remWaiter(d);
+ d->typeData->release();
+ }
+ if (d->cc)
+ d->cc->release();
+
+ for(int ii = 0; ii < d->bindValues.count(); ++ii)
+ QmlEnginePrivate::clear(d->bindValues[ii]);
+ for(int ii = 0; ii < d->parserStatus.count(); ++ii)
+ QmlEnginePrivate::clear(d->parserStatus[ii]);
+}
+
+/*!
+ Returns the component's current \l{QmlComponent::Status} {status}.
+ */
+QmlComponent::Status QmlComponent::status() const
+{
+ Q_D(const QmlComponent);
+
+ if (d->typeData)
+ return Loading;
+ else if (!d->errors.isEmpty())
+ return Error;
+ else if (d->engine && d->cc)
+ return Ready;
+ else
+ return Null;
+}
+
+/*!
+ Returns true if the component is in the Null state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Null.
+*/
+bool QmlComponent::isNull() const
+{
+ return status() == Null;
+}
+
+/*!
+ Returns true if the component is in the Ready state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Ready.
+*/
+bool QmlComponent::isReady() const
+{
+ return status() == Ready;
+}
+
+/*!
+ Returns true if the component is in the Error state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Error.
+*/
+bool QmlComponent::isError() const
+{
+ return status() == Error;
+}
+
+/*!
+ Returns true if the component is in the Loading state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Loading.
+*/
+bool QmlComponent::isLoading() const
+{
+ return status() == Loading;
+}
+
+/*!
+ \fn void QmlComponent::statusChanged(QmlComponent::Status status)
+
+ Emitted whenever the component's status changes. \a status will be the
+ new status.
+*/
+
+/*!
+ Create a QmlComponent with no data and give it the specified
+ \a engine and \a parent. Set the data with setData().
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+}
+
+/*!
+ Create a QmlComponent from the given \a url and give it the
+ specified \a parent and \a engine.
+
+ \sa loadUrl()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QUrl &url, QObject *parent)
+: QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ loadUrl(url);
+}
+
+/*!
+ Create a QmlComponent from the given QML \a data and give it the
+ specified \a parent and \a engine. If \a url is provided, it is used to set
+ the component name, and to provide a base path for items resolved
+ by this component.
+
+ \sa setData()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QByteArray &data, const QUrl &url, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ setData(data,url);
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QmlCompiledComponent *cc, int start, int count, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ d->cc = cc;
+ cc->addref();
+ d->start = start;
+ d->count = count;
+}
+
+/*!
+ Sets the QmlComponent to use the given QML \a data. If \a url
+ is provided, it is used to set the component name and to provide
+ a base path for items resolved by this component.
+*/
+void QmlComponent::setData(const QByteArray &data, const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ d->url = url;
+
+ QmlCompositeTypeData *typeData =
+ d->engine->d_func()->typeManager.getImmediate(data, url);
+
+ if (typeData->status == QmlCompositeTypeData::Waiting) {
+
+ d->typeData = typeData;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(typeData);
+
+ }
+
+ emit statusChanged(status());
+}
+
+/*!
+ Load the QmlComponent from the provided \a url.
+*/
+void QmlComponent::loadUrl(const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ d->url = url;
+
+ QmlCompositeTypeData *data =
+ d->engine->d_func()->typeManager.get(url);
+
+ if (data->status == QmlCompositeTypeData::Waiting) {
+
+ d->typeData = data;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(data);
+
+ }
+
+ emit statusChanged(status());
+}
+
+/*!
+ Return the list of errors that occured during the last compile or create
+ operation. An empty list is returned if isError() is not set.
+*/
+QList<QmlError> QmlComponent::errors() const
+{
+ Q_D(const QmlComponent);
+ if (isError())
+ return d->errors;
+ else
+ return QList<QmlError>();
+}
+
+/*!
+ Return the component URL. This is the URL passed to either the constructor,
+ or the loadUrl() or setData() methods.
+*/
+QUrl QmlComponent::url() const
+{
+ Q_D(const QmlComponent);
+ return d->url;
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlComponentPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ If \a context is 0 (the default), it will create the instance in the
+ engine' s \l {QmlEngine::rootContext()}{root context}.
+*/
+QObject *QmlComponent::create(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ if (!context)
+ context = d->engine->rootContext();
+
+ if (context->engine() != d->engine) {
+ qWarning("QmlComponent::create(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ QObject *rv = beginCreate(context);
+ completeCreate();
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ When QmlComponent constructs an instance, it occurs in three steps:
+ \list 1
+ \i The object hierarchy is created, and constant values are assigned.
+ \i Property bindings are evaluated for the the first time.
+ \i If applicable, QmlParserStatus::componentComplete() is called on objects.
+ \endlist
+ QmlComponent::beginCreate() differs from QmlComponent::create() in that it
+ only performs step 1. QmlComponent::completeCreate() must be called to
+ complete steps 2 and 3.
+
+ This breaking point is sometimes useful when using attached properties to
+ communicate information to an instantiated component, as it allows their
+ initial values to be configured before property bindings take effect.
+*/
+QObject *QmlComponent::beginCreate(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ if (!context) {
+ qWarning("QmlComponent::beginCreate(): Cannot create a component in a null context");
+ return 0;
+ }
+
+ if (context->engine() != d->engine) {
+ qWarning("QmlComponent::beginCreate(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ if (d->completePending) {
+ qWarning("QmlComponent: Cannot create new component instance before completing the previous");
+ return 0;
+ }
+
+ if (!isReady()) {
+ qWarning("QmlComponent: Component is not ready");
+ return 0;
+ }
+
+ if (!d->engine->d_func()->rootComponent)
+ d->engine->d_func()->rootComponent = this;
+
+ QmlContext *ctxt =
+ new QmlContext(context, 0);
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->url = d->cc->url;
+ if(d->start != -1) {
+ // ### FIXME
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->startLine = d->cc->bytecode.at(d->start - 1).line;
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->endLine = d->cc->bytecode.at(d->start - 1).createComponent.endLine;
+ }
+ ctxt->activate();
+
+ QmlVME vme;
+ QObject *rv = vme.run(ctxt, d->cc, d->start, d->count);
+
+ if (vme.isError())
+ d->errors = vme.errors();
+
+ ctxt->deactivate();
+
+ QmlEnginePrivate *ep = d->engine->d_func();
+ if (ep->rootComponent == this) {
+ ep->rootComponent = 0;
+
+ d->bindValues = ep->bindValues;
+ d->parserStatus = ep->parserStatus;
+ ep->bindValues.clear();
+ ep->parserStatus.clear();
+ d->completePending = true;
+ }
+
+ if (rv) {
+ QFx_setParent_noEvent(ctxt, rv);
+ } else {
+ delete ctxt;
+ }
+
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Complete a component creation begin with QmlComponent::beginCreate().
+*/
+void QmlComponent::completeCreate()
+{
+ Q_D(QmlComponent);
+ if (d->completePending) {
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindInit> bi;
+#endif
+ for (int ii = 0; ii < d->bindValues.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bv =
+ d->bindValues.at(ii);
+ for (int jj = 0; jj < bv.count; ++jj) {
+ if(bv.at(jj))
+ bv.at(jj)->init();
+ }
+ QmlEnginePrivate::clear(bv);
+ }
+ }
+
+ for (int ii = 0; ii < d->parserStatus.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlParserStatus> ps =
+ d->parserStatus.at(ii);
+
+ for (int jj = 0; jj < ps.count; ++jj) {
+ QmlParserStatus *status = ps.at(jj);
+ if (status && status->d) {
+ status->d = 0;
+ status->componentComplete();
+ }
+ }
+ QmlEnginePrivate::clear(ps);
+ }
+
+ d->bindValues.clear();
+ d->parserStatus.clear();
+ d->completePending = false;
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
new file mode 100644
index 0000000..e7386d9
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPONENT_H
+#define QMLCOMPONENT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlCompiledComponent;
+class QByteArray;
+class QmlComponentPrivate;
+class QmlEngine;
+class Q_DECLARATIVE_EXPORT QmlComponent : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlComponent)
+
+public:
+ QmlComponent(QObject *parent = 0);
+ QmlComponent(QmlEngine *, QObject *parent=0);
+ QmlComponent(QmlEngine *, const QUrl &url, QObject *parent = 0);
+ QmlComponent(QmlEngine *, const QByteArray &data,
+ const QUrl &baseUrl=QUrl(), QObject *parent=0);
+ virtual ~QmlComponent();
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ bool isNull() const;
+ bool isReady() const;
+ bool isError() const;
+ bool isLoading() const;
+
+ QList<QmlError> errors() const;
+
+ QUrl url() const;
+
+ virtual QObject *create(QmlContext *context = 0);
+ virtual QObject *beginCreate(QmlContext *);
+ virtual void completeCreate();
+
+ void loadUrl(const QUrl &url);
+ void setData(const QByteArray &, const QUrl &baseUrl = QUrl());
+
+Q_SIGNALS:
+ void statusChanged(QmlComponent::Status);
+
+protected:
+ QmlComponent(QmlComponentPrivate &dd, QObject* parent);
+
+private:
+ QmlComponent(QmlEngine *, QmlCompiledComponent *, int, int, QObject *parent);
+
+ friend class QmlVME;
+ friend struct QmlCompositeTypeData;
+};
+QML_DECLARE_TYPE(QmlComponent)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCOMPONENT_H
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
new file mode 100644
index 0000000..254d9ba
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPONENT_P_H
+#define QMLCOMPONENT_P_H
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QList>
+#include <private/qobject_p.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <QtDeclarative/qmlerror.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlComponent;
+class QmlEngine;
+class QmlCompiledComponent;
+
+class QmlComponentPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlComponent)
+
+public:
+ QmlComponentPrivate() : typeData(0), start(-1), count(-1), cc(0), completePending(false), engine(0) {}
+
+ QmlCompositeTypeData *typeData;
+ void typeDataReady();
+
+ void fromTypeData(QmlCompositeTypeData *data);
+
+ QList<QmlError> errors;
+ QUrl url;
+
+ int start;
+ int count;
+ QmlCompiledComponent *cc;
+
+ QList<QmlEnginePrivate::SimpleList<QmlBindableValue> > bindValues;
+ QList<QmlEnginePrivate::SimpleList<QmlParserStatus> > parserStatus;
+
+ bool completePending;
+
+ QmlEngine *engine;
+
+ void clear();
+};
+
+#endif // QMLCOMPONENT_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
new file mode 100644
index 0000000..a5e302c
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qmlcompositetypemanager_p.h>
+#include <private/qmlscriptparser_p.h>
+#include <private/qmlcompiledcomponent_p.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <private/qmlengine_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlcomponent_p.h>
+
+QmlCompositeTypeData::QmlCompositeTypeData()
+: status(Invalid), errorType(NoError), component(0), compiledComponent(0)
+{
+}
+
+QmlCompositeTypeData::~QmlCompositeTypeData()
+{
+ for (int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+
+ if (compiledComponent)
+ compiledComponent->release();
+
+ if (component)
+ delete component;
+}
+
+void QmlCompositeTypeData::addWaiter(QmlComponentPrivate *p)
+{
+ waiters << p;
+}
+
+void QmlCompositeTypeData::remWaiter(QmlComponentPrivate *p)
+{
+ waiters.removeAll(p);
+}
+
+QmlComponent *QmlCompositeTypeData::toComponent(QmlEngine *engine)
+{
+ if (!component) {
+
+ QmlCompiledComponent *cc = toCompiledComponent(engine);
+ if (cc) {
+ component = new QmlComponent(engine, cc, -1, -1, 0);
+ } else {
+ component = new QmlComponent(engine, 0);
+ component->d_func()->url = QUrl(url);
+ component->d_func()->errors = errors;
+ }
+
+ }
+
+ return component;
+}
+
+QmlCompiledComponent *
+QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine)
+{
+ if (status == Complete && !compiledComponent) {
+
+ compiledComponent = new QmlCompiledComponent;
+ compiledComponent->url = QUrl(url);
+ compiledComponent->name = url.toLatin1(); // ###
+
+ QmlCompiler compiler;
+ if (!compiler.compile(engine, this, compiledComponent)) {
+ status = Error;
+ errors = compiler.errors();
+ for(int ii = 0; ii < errors.count(); ++ii)
+ errors[ii].setUrl(url);
+ compiledComponent->release();
+ compiledComponent = 0;
+ }
+
+ // Data is no longer needed once we have a compiled component
+ data.clear();
+ }
+
+ if (compiledComponent)
+ compiledComponent->addref();
+
+ return compiledComponent;
+}
+
+QmlCompositeTypeData::TypeReference::TypeReference()
+: type(0), unit(0)
+{
+}
+
+QmlCompositeTypeManager::QmlCompositeTypeManager(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url)
+{
+ QmlCompositeTypeData *unit = components.value(url.toString());
+
+ if (!unit) {
+ unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->url = url.toString();
+ components.insert(url.toString(), unit);
+
+ loadSource(unit);
+ }
+
+ unit->addref();
+ return unit;
+}
+
+QmlCompositeTypeData *
+QmlCompositeTypeManager::getImmediate(const QByteArray &data, const QUrl &url)
+{
+ QmlCompositeTypeData *unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->url = url.toString();
+ setData(unit, data, url);
+ return unit;
+}
+
+void QmlCompositeTypeManager::clearCache()
+{
+ for (Components::Iterator iter = components.begin(); iter != components.end();) {
+ if ((*iter)->status != QmlCompositeTypeData::Waiting) {
+ (*iter)->release();
+ iter = components.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+
+void QmlCompositeTypeManager::replyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeData *unit = components.value(reply->url().toString());
+ Q_ASSERT(unit);
+
+ if (reply->error() != QNetworkReply::NoError) {
+
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("Network error for URL ") +
+ reply->url().toString();
+
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+
+ } else {
+ QByteArray data = reply->readAll();
+
+ setData(unit, data, reply->url());
+ }
+
+ reply->deleteLater();
+}
+
+void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
+{
+ QUrl url(unit->url);
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QFile file(url.toLocalFile());
+ if (file.open(QFile::ReadOnly)) {
+ QByteArray data = file.readAll();
+ setData(unit, data, url);
+ } else {
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("File error for URL ") + url.toString();
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+ }
+
+ } else {
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(replyFinished()));
+ }
+}
+
+void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit,
+ const QByteArray &data,
+ const QUrl &url)
+{
+ if (!unit->data.parse(data, url)) {
+
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ unit->errors << unit->data.errors();
+ doComplete(unit);
+
+ } else {
+
+ engine->addNameSpacePaths(unit->data.nameSpacePaths());
+ compile(unit);
+
+ }
+}
+
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit)
+{
+ for (int ii = 0; ii < unit->dependants.count(); ++ii) {
+ checkComplete(unit->dependants.at(ii));
+ unit->dependants.at(ii)->release();
+ }
+ unit->dependants.clear();
+
+ while(!unit->waiters.isEmpty()) {
+ QmlComponentPrivate *p = unit->waiters.takeFirst();
+ p->typeDataReady();
+ }
+}
+
+void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
+{
+ if (unit->status != QmlCompositeTypeData::Waiting)
+ return;
+
+ int waiting = 0;
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData *u = unit->types.at(ii).unit;
+
+ if (!u)
+ continue;
+
+ if (u->status == QmlCompositeTypeData::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errors = u->errors;
+ doComplete(unit);
+ return;
+ } else if (u->status == QmlCompositeTypeData::Waiting) {
+ waiting++;
+ }
+ }
+ if (!waiting) {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ }
+}
+
+void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
+{
+ QStringList typeNames = unit->data.types();
+
+ int waiting = 0;
+ for (int ii = 0; ii < typeNames.count(); ++ii) {
+ QByteArray type = typeNames.at(ii).toLatin1();
+
+ QmlCompositeTypeData::TypeReference ref;
+ if (type == QByteArray("Property") ||
+ type == QByteArray("Signal")) {
+ unit->types << ref;
+ continue;
+ }
+
+ ref.type = QmlMetaType::qmlType(type);
+ if (ref.type) {
+ unit->types << ref;
+ continue;
+ }
+
+ QUrl url = engine->componentUrl(QUrl(QLatin1String(type + ".qml")), QUrl(unit->url));
+ QmlCompositeTypeData *urlUnit = components.value(url.toString());
+
+ if (!urlUnit) {
+ urlUnit = new QmlCompositeTypeData;
+ urlUnit->status = QmlCompositeTypeData::Waiting;
+ urlUnit->url = url.toString();
+ components.insert(url.toString(), urlUnit);
+
+ loadSource(urlUnit);
+ }
+
+ ref.unit = urlUnit;
+ switch(urlUnit->status) {
+ case QmlCompositeTypeData::Invalid:
+ case QmlCompositeTypeData::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->url);
+ error.setDescription(tr("Type %1 unavailable").arg(QLatin1String(type)));
+ unit->errors << error;
+ }
+ if (urlUnit->errorType != QmlCompositeTypeData::AccessError)
+ unit->errors << urlUnit->errors;
+ doComplete(unit);
+ return;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ unit->addref();
+ ref.unit->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ unit->types << ref;
+ }
+
+ if (waiting) {
+ unit->status = QmlCompositeTypeData::Waiting;
+ } else {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ }
+}
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
new file mode 100644
index 0000000..9312819
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPOSITETYPEMANAGER_P_H
+#define QMLCOMPOSITETYPEMANAGER_P_H
+
+#include <QtCore/qglobal.h>
+#include <private/qmlscriptparser_p.h>
+#include <private/qmlrefcount_p.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlCompiledComponent;
+class QmlComponentPrivate;
+class QmlComponent;
+class QmlDomDocument;
+struct QmlCompositeTypeData : public QmlRefCount
+{
+ QmlCompositeTypeData();
+ virtual ~QmlCompositeTypeData();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+ enum ErrorType {
+ NoError,
+ AccessError,
+ GeneralError
+ };
+ ErrorType errorType;
+
+ QList<QmlError> errors;
+
+ QString url;
+ QList<QmlCompositeTypeData *> dependants;
+
+ // Return a QmlComponent if the QmlCompositeTypeData is not in the Waiting
+ // state. The QmlComponent is owned by the QmlCompositeTypeData, so a
+ // reference should be kept to keep the QmlComponent alive.
+ QmlComponent *toComponent(QmlEngine *);
+ // Return a QmlCompiledComponent if possible, or 0 if an error
+ // occurs
+ QmlCompiledComponent *toCompiledComponent(QmlEngine *);
+
+ struct TypeReference
+ {
+ TypeReference();
+
+ QmlType *type;
+ QmlCompositeTypeData *unit;
+ };
+
+ QList<TypeReference> types;
+
+ // Add or remove p as a waiter. When the QmlCompositeTypeData becomes
+ // ready, the QmlComponentPrivate::typeDataReady() method will be invoked on
+ // p. The waiter is automatically removed when the typeDataReady() method
+ // is invoked, so there is no need to call remWaiter() in this case.
+ void addWaiter(QmlComponentPrivate *p);
+ void remWaiter(QmlComponentPrivate *p);
+
+private:
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+ friend class QmlDomDocument;
+
+ QmlScriptParser data;
+ QList<QmlComponentPrivate *> waiters;
+ QmlComponent *component;
+ QmlCompiledComponent *compiledComponent;
+};
+
+class QmlCompositeTypeManager : public QObject
+{
+ Q_OBJECT
+public:
+ QmlCompositeTypeManager(QmlEngine *);
+
+ // Return a QmlCompositeTypeData for url. The QmlCompositeTypeData may be
+ // cached.
+ QmlCompositeTypeData *get(const QUrl &url);
+ // Return a QmlCompositeTypeData for data, with the provided base url. The
+ // QmlCompositeTypeData will not be cached.
+ QmlCompositeTypeData *getImmediate(const QByteArray &data, const QUrl &url);
+
+ // Clear cached types. Only types that aren't in the Waiting state will
+ // be cleared.
+ void clearCache();
+
+private Q_SLOTS:
+ void replyFinished();
+
+private:
+ void loadSource(QmlCompositeTypeData *);
+ void compile(QmlCompositeTypeData *);
+ void setData(QmlCompositeTypeData *, const QByteArray &, const QUrl &);
+
+ void doComplete(QmlCompositeTypeData *);
+ void checkComplete(QmlCompositeTypeData *);
+
+ QmlEngine *engine;
+ typedef QHash<QString, QmlCompositeTypeData *> Components;
+ Components components;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCOMPOSITETYPEMANAGER_P_H
+
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
new file mode 100644
index 0000000..e5016f2
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -0,0 +1,500 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmlcontext.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmlengine_p.h>
+#include <qmlengine.h>
+#include <qscriptengine.h>
+#include <QtCore/qvarlengtharray.h>
+
+#include <qdebug.h>
+
+// 6-bits
+#define MAXIMUM_DEFAULT_OBJECTS 63
+
+QT_BEGIN_NAMESPACE
+
+QmlContextPrivate::QmlContextPrivate()
+: parent(0), engine(0), notifyIndex(-1), highPriorityCount(0),
+ startLine(-1), endLine(-1)
+{
+}
+
+void QmlContextPrivate::dump()
+{
+ dump(0);
+}
+
+void QmlContextPrivate::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ if (parent)
+ parent->d_func()->dump(depth + 1);
+}
+
+void QmlContextPrivate::destroyed(QObject *obj)
+{
+ defaultObjects.removeAll(obj);
+
+ QVariant variantObject = QVariant::fromValue(obj);
+ QVarLengthArray<int> notifies;
+ for (int ii = 0; ii < propertyValues.count(); ++ii) {
+ if (propertyValues.at(ii) == variantObject) {
+ propertyValues[ii] = QVariant();
+ notifies.append(ii);
+ }
+ }
+
+ // ### Work around bug in shutdown
+ // for (int ii = 0; ii < notifies.count(); ++ii) {
+ // QMetaObject::activate(q, notifies[ii] + notifyIndex, 0);
+ // }
+}
+
+void QmlContextPrivate::init()
+{
+ Q_Q(QmlContext);
+
+ if (parent)
+ parent->d_func()->childContexts.insert(q);
+
+ //set scope chain
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue scopeObj =
+ scriptEngine->newObject(engine->d_func()->contextClass, scriptEngine->newVariant(QVariant::fromValue((QObject*)q)));
+ if (!parent)
+ scopeChain.append(scriptEngine->globalObject());
+ else
+ scopeChain = parent->d_func()->scopeChain;
+ scopeChain.prepend(scopeObj);
+
+ contextData.context = q;
+}
+
+void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
+{
+ if (defaultObjects.count() >= (MAXIMUM_DEFAULT_OBJECTS - 1)) {
+ qWarning("QmlContext: Cannot have more than %d default objects on "
+ "one bind context.", MAXIMUM_DEFAULT_OBJECTS - 1);
+ return;
+ }
+
+ if (priority == HighPriority) {
+ defaultObjects.insert(highPriorityCount++, object);
+ } else {
+ defaultObjects.append(object);
+ }
+ QObject::connect(object, SIGNAL(destroyed(QObject*)),
+ q_ptr, SLOT(objectDestroyed(QObject*)));
+}
+
+
+/*!
+ \class QmlContext
+ \brief The QmlContext class defines a context within a QML engine.
+ \mainclass
+
+ Contexts allow data to be exposed to the QML components instantiated by the
+ QML engine.
+
+ Each QmlContext contains a set of properties, distinct from
+ its QObject properties, that allow data to be
+ explicitly bound to a context by name. The context properties are defined or
+ updated by calling QmlContext::setContextProperty(). The following example shows
+ a Qt model being bound to a context and then accessed from a QML file.
+
+ \code
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("myModel", modelData);
+
+ QmlComponent component(&engine, "ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ To simplify binding and maintaining larger data sets, QObject's can be
+ added to a QmlContext. These objects are known as the context's default
+ objects. In this case all the properties of the QObject are
+ made available by name in the context, as though they were all individually
+ added by calling QmlContext::setContextProperty(). Changes to the property's
+ values are detected through the property's notify signal. This method is
+ also slightly more faster than manually adding property values.
+
+ The following example has the same effect as the one above, but it is
+ achieved using a default object.
+
+ \code
+ class MyDataSet : ... {
+ ...
+ Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged);
+ ...
+ };
+
+ MyDataSet myDataSet;
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.addDefaultObject(&myDataSet);
+
+ QmlComponent component(&engine, "ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ Each context may have up to 32 default objects, and objects added first take
+ precedence over those added later. All properties added explicitly by
+ QmlContext::setContextProperty() take precedence over default object properties.
+
+ Contexts are hierarchal, with the \l {QmlEngine::rootContext()}{root context}
+ being created by the QmlEngine. A component instantiated in a given context
+ has access to that context's data, as well as the data defined by its
+ ancestor contexts. Data values (including those added implicitly by the
+ default objects) in a context override those in ancestor contexts. Data
+ that should be available to all components instantiated by the QmlEngine
+ should be added to the \l {QmlEngine::rootContext()}{root context}.
+
+ In the following example,
+
+ \code
+ QmlEngine engine;
+ QmlContext context1(engine.rootContext());
+ QmlContext context2(&context1);
+ QmlContext context3(&context2);
+
+ context1.setContextProperty("a", 12);
+ context2.setContextProperty("b", 13);
+ context3.setContextProperty("a", 14);
+ context3.setContextProperty("c", 14);
+ \endcode
+
+ a QML component instantiated in context1 would have access to the "a" data,
+ a QML component instantiated in context2 would have access to the "a" and
+ "b" data, and a QML component instantiated in context3 would have access to
+ the "a", "b" and "c" data - although its "a" data would return 14, unlike
+ that in context1 or context2.
+*/
+
+/*! \internal */
+QmlContext::QmlContext(QmlEngine *e)
+: QObject(*(new QmlContextPrivate))
+{
+ Q_D(QmlContext);
+ d->engine = e;
+ d->init();
+}
+
+/*!
+ Create a new QmlContext with the given \a parentContext, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
+ Destroys the QmlContext.
+
+ Any expressions, or sub-contexts dependent on this context will be
+ invalidated, but not destroyed (unless they are parented to the QmlContext
+ object).
+ */
+QmlContext::~QmlContext()
+{
+ Q_D(QmlContext);
+ if (d->parent)
+ d->parent->d_func()->childContexts.remove(this);
+
+ for (QSet<QmlContext *>::ConstIterator iter = d->childContexts.begin();
+ iter != d->childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ (*iter)->d_func()->parent = 0;
+ }
+
+ for (QSet<QmlExpression *>::ConstIterator iter =
+ d->childExpressions.begin();
+ iter != d->childExpressions.end();
+ ++iter) {
+ (*iter)->d->ctxt = 0;
+ }
+
+ for (int ii = 0; ii < d->contextObjects.count(); ++ii) {
+ QObjectPrivate *p = QObjectPrivate::get(d->contextObjects.at(ii));
+ QmlSimpleDeclarativeData *data =
+ static_cast<QmlSimpleDeclarativeData *>(p->declarativeData);
+ if(data && (data->flags & QmlSimpleDeclarativeData::Extended)) {
+ data->context = 0;
+ } else {
+ p->declarativeData = 0;
+ }
+ }
+ d->contextObjects.clear();
+}
+
+void QmlContextPrivate::invalidateEngines()
+{
+ if (!engine)
+ return;
+ engine = 0;
+ for (QSet<QmlContext *>::ConstIterator iter = childContexts.begin();
+ iter != childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ }
+}
+
+/*!
+ Return the context's QmlEngine, or 0 if the context has no QmlEngine or the
+ QmlEngine was destroyed.
+*/
+QmlEngine *QmlContext::engine() const
+{
+ Q_D(const QmlContext);
+ return d->engine;
+}
+
+/*!
+ Return the context's parent QmlContext, or 0 if this context has no
+ parent or if the parent has been destroyed.
+*/
+QmlContext *QmlContext::parentContext() const
+{
+ Q_D(const QmlContext);
+ return d->parent;
+}
+
+/*!
+ Add a default \a object to this context. The object will be added after
+ any existing default objects.
+*/
+void QmlContext::addDefaultObject(QObject *object)
+{
+ Q_D(QmlContext);
+ d->addDefaultObject(object, QmlContextPrivate::NormalPriority);
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+*/
+void QmlContext::setContextProperty(const QString &name, const QVariant &value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ if (QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ setContextProperty(name, o);
+ } else {
+ QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
+ if(iter == d->propertyNames.end()) {
+ d->propertyNames.insert(name, d->propertyValues.count());
+ d->propertyValues.append(value);
+ } else {
+ d->propertyValues[*iter] = value;
+ QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ }
+ }
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+
+ QmlContext does \b not take ownership of \a value.
+*/
+void QmlContext::setContextProperty(const QString &name, QObject *value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ QObject::connect(value, SIGNAL(destroyed(QObject*)),
+ this, SLOT(objectDestroyed(QObject*)));
+
+ QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
+ if(iter == d->propertyNames.end()) {
+ d->propertyNames.insert(name, d->propertyValues.count());
+ d->propertyValues.append(QVariant::fromValue(value));
+ } else {
+ int idx = *iter;
+ if (QmlMetaType::isObject(d->propertyValues.at(idx).userType())) {
+ QObject *old = QmlMetaType::toQObject(d->propertyValues.at(idx));
+ QObject::disconnect(old, SIGNAL(destroyed(QObject*)),
+ this, SLOT(objectDestroyed(QObject*)));
+ }
+ d->propertyValues[*iter] = QVariant::fromValue(value);
+ QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ }
+}
+
+/*!
+ Activate this bind context.
+
+ \sa QmlEngine::activeContext() QmlContext::activeContext()
+*/
+void QmlContext::activate()
+{
+ QmlEnginePrivate *ep = engine()->d_func();
+ ep->activeContexts.push(this);
+ ep->setCurrentBindContext(this);
+ ep->contextActivated(this);
+}
+
+/*!
+ Deactivate this bind context. The previously active bind context will
+ become active, or, if there was no previously active bind context, no
+ context will be active.
+
+ \sa QmlEngine::activeContext() QmlContext::activeContext()
+*/
+void QmlContext::deactivate()
+{
+ QmlEnginePrivate *ep = engine()->d_func();
+ Q_ASSERT(ep->activeContexts.top() == this);
+ ep->activeContexts.pop();
+ if (ep->activeContexts.isEmpty())
+ ep->setCurrentBindContext(0);
+ else
+ ep->setCurrentBindContext(ep->activeContexts.top());
+ ep->contextDeactivated(this);
+}
+
+/*!
+ Returns the currently active context, or 0 if no context is active.
+
+ This method is thread-safe. The active context is maintained individually
+ for each thread. This method is equivalent to
+ \code
+ QmlEngine::activeEngine()->activeContext()
+ \endcode
+*/
+QmlContext *QmlContext::activeContext()
+{
+ QmlEngine *engine = QmlEngine::activeEngine();
+ if (engine)
+ return engine->activeContext();
+ else
+ return 0;
+}
+
+/*!
+ Resolves the URL \a src relative to the URL of the
+ containing component. If \a src is absolute, it is
+ simply returned. If there is no containing component,
+ an empty URL is returned.
+
+ \sa QmlEngine::componentUrl(), setBaseUrl()
+*/
+QUrl QmlContext::resolvedUrl(const QUrl &src)
+{
+ QmlContext *ctxt = this;
+ if (src.isRelative()) {
+ if (ctxt) {
+ while(ctxt) {
+ if(ctxt->d_func()->url.isValid())
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if (ctxt)
+ return ctxt->d_func()->url.resolved(src);
+ }
+ return QUrl();
+ } else {
+ return src;
+ }
+}
+
+/*!
+ Resolves the component URI \a src relative to the URL of the
+ containing component, and according to the
+ \l {QmlEngine::nameSpacePaths()} {namespace paths} of the
+ context's engine, returning the resolved URL.
+
+ \sa QmlEngine::componentUrl(), setBaseUrl()
+*/
+QUrl QmlContext::resolvedUri(const QUrl &src)
+{
+ QmlContext *ctxt = this;
+ if (src.isRelative()) {
+ if (ctxt) {
+ while(ctxt) {
+ if (ctxt->d_func()->url.isValid())
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if (ctxt)
+ return ctxt->d_func()->engine->componentUrl(src, ctxt->d_func()->url);
+ }
+ return QUrl();
+ } else {
+ return ctxt->d_func()->engine->componentUrl(src, QUrl());
+ }
+}
+
+/*!
+ Explicitly sets the url both resolveUri() and resolveUrl() will
+ use for relative references to \a baseUrl.
+
+ Calling this function will override the url of the containing
+ component used by default.
+
+ \sa resolvedUrl(), resolvedUri()
+*/
+void QmlContext::setBaseUrl(const QUrl &baseUrl)
+{
+ d_func()->url = baseUrl;
+}
+
+void QmlContext::objectDestroyed(QObject *object)
+{
+ Q_D(QmlContext);
+ d->destroyed(object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
new file mode 100644
index 0000000..935c7ca
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXT_H
+#define QMLCONTEXT_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlEngine;
+class QmlRefCount;
+class QmlContextPrivate;
+class Q_DECLARATIVE_EXPORT QmlContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlContext)
+
+public:
+ QmlContext(QmlContext *parent, QObject *objParent=0);
+ virtual ~QmlContext();
+
+ QmlEngine *engine() const;
+ QmlContext *parentContext() const;
+
+ void addDefaultObject(QObject *);
+ void setContextProperty(const QString &, QObject *);
+ void setContextProperty(const QString &, const QVariant &);
+
+ void activate();
+ void deactivate();
+
+ static QmlContext *activeContext();
+
+ QUrl resolvedUri(const QUrl &);
+ QUrl resolvedUrl(const QUrl &);
+
+ void setBaseUrl(const QUrl &);
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *);
+
+private:
+ friend class QmlEngine;
+ friend class QmlEnginePrivate;
+ friend class QmlExpression;
+ friend class QmlBasicScript;
+ friend class QmlContextScriptClass;
+ friend class QmlObjectScriptClass;
+ friend class QmlComponent;
+ friend class QmlScriptPrivate;
+ friend class QmlBoundSignalProxy;
+ friend class QmlSimpleDeclarativeData;
+ QmlContext(QmlEngine *);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCONTEXT_H
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
new file mode 100644
index 0000000..4d88fc2
--- /dev/null
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXT_P_H
+#define QMLCONTEXT_P_H
+
+#include <QtDeclarative/qmlcontext.h>
+#include <private/qobject_p.h>
+#include <private/qmldeclarativedata_p.h>
+#include <QtCore/qhash.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+class QmlContext;
+class QmlExpression;
+class QmlEngine;
+class QmlExpression;
+class QmlCompiledComponent;
+
+class QmlContextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlContext)
+public:
+ QmlContextPrivate();
+
+ QmlContext *parent;
+ QmlEngine *engine;
+
+ QHash<QString, int> propertyNames;
+ QList<QVariant> propertyValues;
+ int notifyIndex;
+
+ QObjectList defaultObjects;
+ int highPriorityCount;
+
+ QScriptValueList scopeChain;
+
+ QUrl url;
+ QByteArray typeName;
+ int startLine;
+ int endLine;
+
+ void init();
+
+ void dump();
+ void dump(int depth);
+
+ void destroyed(QObject *);
+
+ enum Priority {
+ HighPriority,
+ NormalPriority
+ };
+ void addDefaultObject(QObject *, Priority);
+
+ void invalidateEngines();
+ QSet<QmlContext *> childContexts;
+ QSet<QmlExpression *> childExpressions;
+
+ QmlSimpleDeclarativeData contextData;
+ QObjectList contextObjects;
+};
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXT_P_H
diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp
new file mode 100644
index 0000000..2e8c8f6
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcustomparser_p.h"
+#include "qmlcustomparser_p_p.h"
+#include "qmlparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+/*!
+ \class QmlCustomParser
+ \brief The QmlCustomParser class allows you to add new arbitrary types to QML.
+ \internal
+
+ By subclassing QmlCustomParser, you can add an XML parser for
+ building a particular type.
+
+ The subclass must implement compile() and create(), and define
+ itself in the meta type system with one of the macros:
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER(Name, parserClass)
+ \endcode
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER_NS("XmlNamespaceUri", Name, parserClass)
+ \endcode
+*/
+
+/*
+ \fn QByteArray QmlCustomParser::compile(QXmlStreamReader& reader, bool *ok)
+
+ Upon entry to this function, \a reader is positioned on a
+ QXmlStreamReader::StartElement with the name specified when the
+ class was defined with the QML_DEFINE_CUSTOM_PARSER macro.
+
+ The custom parser must consume tokens from \a reader until the
+ EndElement matching the initial start element is reached, or until
+ error.
+
+ On return, \c *ok indicates success.
+
+ The returned QByteArray contains data meaningful only to the
+ custom parser; the type engine will pass this same data to
+ create() when making an instance of the data.
+
+ The QByteArray may be cached between executions of the system, so
+ it must contain correctly-serialized data (not, for example,
+ pointers to stack objects).
+*/
+
+/*
+ \fn QVariant QmlCustomParser::create(const QByteArray &data)
+
+ This function returns a QVariant containing the value represented
+ by \a data, which is a block of data previously returned by a call
+ to compile().
+
+ If the compile is for a type, the variant should be a pointer to
+ the correctly-named QObject subclass (i.e. the one defined by
+ QML_DEFINE_TYPE for the same-named type as this custom parser is
+ defined for).
+*/
+
+QmlCustomParserNode
+QmlCustomParserNodePrivate::fromObject(QmlParser::Object *root)
+{
+ QmlCustomParserNode rootNode;
+ rootNode.d->name = root->typeName;
+
+ for(QHash<QByteArray, Property *>::Iterator iter = root->properties.begin();
+ iter != root->properties.end();
+ ++iter) {
+
+ Property *p = *iter;
+
+ rootNode.d->properties << fromProperty(p);
+ }
+
+ return rootNode;
+}
+
+#include <QtCore/qdebug.h>
+QmlCustomParserProperty
+QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p)
+{
+ QmlCustomParserProperty prop;
+ prop.d->name = p->name;
+ prop.d->isList = (p->values.count() > 1);
+
+ if (p->value) {
+ QmlCustomParserNode node = fromObject(p->value);
+ QList<QmlCustomParserProperty> props = node.properties();
+ for (int ii = 0; ii < props.count(); ++ii)
+ prop.d->values << QVariant::fromValue(props.at(ii));
+ } else {
+ for(int ii = 0; ii < p->values.count(); ++ii) {
+ Value *v = p->values.at(ii);
+
+ if(v->object) {
+ QmlCustomParserNode node = fromObject(v->object);
+ prop.d->values << QVariant::fromValue(node);
+ } else {
+ prop.d->values << QVariant::fromValue(v->value);
+ }
+
+ }
+ }
+
+ return prop;
+}
+
+QmlCustomParserNode::QmlCustomParserNode()
+: d(new QmlCustomParserNodePrivate)
+{
+}
+
+QmlCustomParserNode::QmlCustomParserNode(const QmlCustomParserNode &other)
+: d(new QmlCustomParserNodePrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserNode &QmlCustomParserNode::operator=(const QmlCustomParserNode &other)
+{
+ d->name = other.d->name;
+ d->properties = other.d->properties;
+ return *this;
+}
+
+QmlCustomParserNode::~QmlCustomParserNode()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserNode::name() const
+{
+ return d->name;
+}
+
+QList<QmlCustomParserProperty> QmlCustomParserNode::properties() const
+{
+ return d->properties;
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty()
+: d(new QmlCustomParserPropertyPrivate)
+{
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty(const QmlCustomParserProperty &other)
+: d(new QmlCustomParserPropertyPrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserProperty &QmlCustomParserProperty::operator=(const QmlCustomParserProperty &other)
+{
+ d->name = other.d->name;
+ d->isList = other.d->isList;
+ d->values = other.d->values;
+ return *this;
+}
+
+QmlCustomParserProperty::~QmlCustomParserProperty()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserProperty::name() const
+{
+ return d->name;
+}
+
+bool QmlCustomParserProperty::isList() const
+{
+ return d->isList;
+}
+
+QList<QVariant> QmlCustomParserProperty::assignedValues() const
+{
+ return d->values;
+}
+
+QByteArray QmlCustomParser::compile(const QList<QmlCustomParserProperty> &, bool *ok)
+{
+ Q_UNUSED(ok);
+ return QByteArray();
+}
+
+void QmlCustomParser::setCustomData(QObject *, const QByteArray &)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h
new file mode 100644
index 0000000..75da579
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCUSTOMPARSER_H
+#define QMLCUSTOMPARSER_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qxmlstream.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlCustomParserPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserProperty
+{
+public:
+ QmlCustomParserProperty();
+ QmlCustomParserProperty(const QmlCustomParserProperty &);
+ QmlCustomParserProperty &operator=(const QmlCustomParserProperty &);
+ ~QmlCustomParserProperty();
+
+ QByteArray name() const;
+
+ bool isList() const;
+ // Will be one of QmlParser::Variant, QmlCustomParserProperty or
+ // QmlCustomParserNode
+ QList<QVariant> assignedValues() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ friend class QmlCustomParserPropertyPrivate;
+ QmlCustomParserPropertyPrivate *d;
+};
+Q_DECLARE_METATYPE(QmlCustomParserProperty)
+
+class QmlCustomParserNodePrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserNode
+{
+public:
+ QmlCustomParserNode();
+ QmlCustomParserNode(const QmlCustomParserNode &);
+ QmlCustomParserNode &operator=(const QmlCustomParserNode &);
+ ~QmlCustomParserNode();
+
+ QByteArray name() const;
+
+ QList<QmlCustomParserProperty> properties() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ QmlCustomParserNodePrivate *d;
+};
+Q_DECLARE_METATYPE(QmlCustomParserNode)
+
+class Q_DECLARATIVE_EXPORT QmlCustomParser
+{
+public:
+ virtual ~QmlCustomParser() {}
+
+ virtual QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+#define QML_DEFINE_CUSTOM_TYPE(TYPE, NAME, CUSTOMTYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterCustomType<TYPE>(#NAME, #TYPE, new CUSTOMTYPE));
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/qml/qmlcustomparser_p_p.h b/src/declarative/qml/qmlcustomparser_p_p.h
new file mode 100644
index 0000000..96e9b32
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCUSTOMPARSER_P_H
+#define QMLCUSTOMPARSER_P_H
+
+#include <QtCore/qglobal.h>
+#include "qmlcustomparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlParser
+{
+ class Object;
+ class Property;
+};
+
+class QmlCustomParserNodePrivate
+{
+public:
+ QByteArray name;
+ QList<QmlCustomParserProperty> properties;
+
+ static QmlCustomParserNode fromObject(QmlParser::Object *);
+ static QmlCustomParserProperty fromProperty(QmlParser::Property *);
+};
+
+class QmlCustomParserPropertyPrivate
+{
+public:
+ QmlCustomParserPropertyPrivate()
+ : isList(false) {}
+
+ QByteArray name;
+ bool isList;
+ QList<QVariant> values;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCUSTOMPARSER_P_H
diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h
new file mode 100644
index 0000000..fb7a015
--- /dev/null
+++ b/src/declarative/qml/qmldeclarativedata_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDECLARATIVEDATA_P_H
+#define QMLDECLARATIVEDATA_P_H
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlSimpleDeclarativeData : public QDeclarativeData
+{
+public:
+ QmlSimpleDeclarativeData() : flags(0), context(0) {}
+
+ virtual void destroyed(QObject *);
+ enum Flag { Extended = 0x00000001 };
+ quint32 flags;
+ QmlContext *context;
+};
+
+class QmlExtendedDeclarativeData : public QmlSimpleDeclarativeData
+{
+public:
+ QmlExtendedDeclarativeData() { flags = Extended; }
+
+ virtual void destroyed(QObject *);
+ QHash<int, QObject *> attachedProperties;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLDECLARATIVEDATA_P_H
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
new file mode 100644
index 0000000..0ebbbfb
--- /dev/null
+++ b/src/declarative/qml/qmldom.cpp
@@ -0,0 +1,1544 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldom.h"
+#include "qmldom_p.h"
+#include "private/qmlcompiler_p.h"
+#include "private/qmlengine_p.h"
+#include "qmlcompiledcomponent_p.h"
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP)
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate()
+: root(0)
+{
+}
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate(const QmlDomDocumentPrivate &other)
+: QSharedData(other), root(0)
+{
+ root = other.root;
+ if (root) root->addref();
+}
+
+QmlDomDocumentPrivate::~QmlDomDocumentPrivate()
+{
+ if (root) root->release();
+}
+
+/*!
+ \class QmlDomDocument
+ \internal
+ \brief The QmlDomDocument class represents the root of a QML document
+
+ A QML document is a self-contained snippet of QML, usually contained in a
+ single file. Each document has a version number, accessible through
+ QmlDomDocument::version(), and a root object, accessible through
+ QmlDomDocument::rootObject().
+
+ The QmlDomDocument class allows the programmer to load a QML document, by
+ calling QmlDomDocument::load(), manipulate it and save it to textual form
+ by calling QmlDomDocument::save(). By using the QML DOM API, editors can
+ non-destructively modify a QML document even if they only understand a
+ subset of the total QML functionality.
+
+ The following example loads a QML file from disk, and prints out its root
+ object type and the properties assigned in the root object.
+ \code
+ QFile file(inputFileName);
+ file.open(QIODevice::ReadOnly);
+ QByteArray xmlData = file.readAll();
+
+ QDomDocument document;
+ document.load(xmlData);
+
+ QDomObject rootObject = document.rootObject();
+ qDebug() << rootObject.objectType();
+ foreach(QmlDomProperty property, rootObject.properties())
+ qDebug() << property.propertyName();
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument()
+: d(new QmlDomDocumentPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument(const QmlDomDocument &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomDocument
+*/
+QmlDomDocument::~QmlDomDocument()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomDocument.
+*/
+QmlDomDocument &QmlDomDocument::operator=(const QmlDomDocument &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the version number of the Qml document. Currently only version
+ 1 exists.
+*/
+int QmlDomDocument::version() const
+{
+ return 1;
+}
+
+/*!
+ Return the URIs listed by "import <dir>" in the qml.
+*/
+QList<QUrl> QmlDomDocument::imports() const
+{
+ return d->imports;
+}
+
+/*!
+ Loads a QmlDomDocument from \a data. \a data should be valid QML
+ data. On success, true is returned. If the \a data is malformed, false
+ is returned and QmlDomDocument::loadError() contains an error description.
+
+ \sa QmlDomDocument::save() QmlDomDocument::loadError()
+*/
+bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data, const QUrl &url)
+{
+ Q_UNUSED(engine);
+ d->errors.clear();
+ d->imports.clear();
+
+ QmlCompiledComponent component;
+ QmlCompiler compiler;
+
+ QmlCompositeTypeData *td = ((QmlEnginePrivate *)QmlEnginePrivate::get(engine))->typeManager.getImmediate(data, url);
+
+ if(td->status == QmlCompositeTypeData::Error) {
+ d->errors = td->errors;
+ td->release();
+ return false;
+ } else if(td->status == QmlCompositeTypeData::Waiting) {
+ QmlError error;
+ error.setDescription(QLatin1String("QmlDomDocument supports local types only"));
+ d->errors << error;
+ td->release();
+ return false;
+ }
+
+ compiler.compile(engine, td, &component);
+
+ if (compiler.isError()) {
+ d->errors = compiler.errors();
+ td->release();
+ return false;
+ }
+
+ for (int i = 0; i < td->data.imports().size(); ++i) {
+ d->imports += QUrl(td->data.imports().at(i).uri);
+ }
+
+ if (td->data.tree()) {
+ if (compilerDump()) {
+ qWarning() << "-AST------------------------------------------------------------------------------";
+ td->data.tree()->dump();
+ qWarning() << "----------------------------------------------------------------------------------";
+ }
+ d->root = td->data.tree();
+ d->root->addref();
+ }
+
+ return true;
+}
+
+
+/*!
+ Returns the last load errors. The load errors will be reset after a
+ successful call to load().
+
+ \sa load()
+*/
+QList<QmlError> QmlDomDocument::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Return a saved copy of the QmlDomDocument. The returned data will be valid
+ QML XML data.
+
+ \sa load()
+*/
+QByteArray QmlDomDocument::save() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns the document's root object, or an invalid QmlDomObject if the
+ document has no root.
+
+ In the sample QML below, the root object will be the QFxItem type.
+ \qml
+Item {
+ Text {
+ text: "Hello World"
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomDocument::rootObject() const
+{
+ QmlDomObject rv;
+ rv.d->object = d->root;
+ if (rv.d->object) rv.d->object->addref();
+ return rv;
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate()
+: property(0)
+{
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate(const QmlDomPropertyPrivate &other)
+: QSharedData(other), property(0)
+{
+ property = other.property;
+ if (property) property->addref();
+}
+
+QmlDomPropertyPrivate::~QmlDomPropertyPrivate()
+{
+ if (property) property->release();
+}
+
+/*!
+ \class QmlDomProperty
+ \internal
+ \brief The QmlDomProperty class represents one property assignment in the
+ QML DOM tree
+
+ Properties in QML can be assigned QML \l {QmlDomValue}{values}.
+
+ \sa QmlDomObject
+*/
+
+/*!
+ Construct an invalid QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty()
+: d(new QmlDomPropertyPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty(const QmlDomProperty &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomProperty.
+*/
+QmlDomProperty::~QmlDomProperty()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomProperty.
+*/
+QmlDomProperty &QmlDomProperty::operator=(const QmlDomProperty &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the name of this property.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ As illustrated above, a property name can be a simple string, such as "x" or
+ "y", or a more complex "dot property", such as "font.bold". In both cases
+ the full name is returned ("x", "y" and "font.bold") by this method.
+
+ For dot properties, a split version of the name can be accessed by calling
+ QmlDomProperty::propertyNameParts().
+
+ \sa QmlDomProperty::propertyNameParts()
+*/
+QByteArray QmlDomProperty::propertyName() const
+{
+ return d->propertyName;
+}
+
+/*!
+ Return the name of this property, split into multiple parts in the case
+ of dot properties.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ For each of the properties shown above, this method would return ("x"),
+ ("y") and ("font", "bold").
+
+ \sa QmlDomProperty::propertyName()
+*/
+QList<QByteArray> QmlDomProperty::propertyNameParts() const
+{
+ if (d->propertyName.isEmpty()) return QList<QByteArray>();
+ else return d->propertyName.split('.');
+}
+
+/*!
+ Return true if this property is used as a default property in the QML
+ document.
+
+ \qml
+<Text text="hello"/>
+<Text>hello</Text>
+ \endqml
+
+ The above two examples return the same DOM tree, except that the second has
+ the default property flag set on the text property. Observe that whether
+ or not a property has isDefaultProperty set is determined by how the
+ property is used, and not only by whether the property is the types default
+ property.
+*/
+bool QmlDomProperty::isDefaultProperty() const
+{
+ return d->property && d->property->isDefault;
+}
+
+/*!
+ Returns the QmlDomValue that is assigned to this property, or an invalid
+ QmlDomValue if no value is assigned.
+*/
+QmlDomValue QmlDomProperty::value() const
+{
+ QmlDomValue rv;
+ if (d->property) {
+ rv.d->property = d->property;
+ rv.d->value = d->property->values.at(0);
+ rv.d->property->addref();
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Sets the QmlDomValue that is assigned to this property to \a value.
+*/
+void QmlDomProperty::setValue(const QmlDomValue &value)
+{
+ Q_UNUSED(value);
+ qWarning("QmlDomProperty::setValue(const QmlDomValue &): Not Implemented");
+}
+
+/*!
+ Returns the position in the input data where the property ID startd, or 0 if
+ the property is invalid.
+*/
+int QmlDomProperty::position() const
+{
+ if (d && d->property) {
+ return d->property->location.range.offset;
+ } else
+ return 0;
+}
+
+/*!
+ Returns the length in the input data from where the property ID started upto
+ the end of it, or 0 if the property is invalid.
+*/
+int QmlDomProperty::length() const
+{
+ if (d && d->property)
+ return d->property->location.range.length;
+ else
+ return 0;
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate()
+: object(0), isVirtualComponent(false)
+{
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate(const QmlDomObjectPrivate &other)
+: QSharedData(other), object(0), isVirtualComponent(false)
+{
+ object = other.object;
+ if (object) object->addref();
+ isVirtualComponent = other.isVirtualComponent;
+}
+
+QmlDomObjectPrivate::~QmlDomObjectPrivate()
+{
+ if (object) object->release();
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties() const
+{
+ Properties rv;
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ object->properties.begin();
+ iter != object->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+ return rv;
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties(QmlParser::Property *property) const
+{
+ Properties rv;
+
+ if (property->value) {
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ property->value->properties.begin();
+ iter != property->value->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+
+ QByteArray name(property->name + ".");
+ for (Properties::Iterator iter = rv.begin(); iter != rv.end(); ++iter)
+ iter->second.prepend(name);
+
+ } else {
+ rv << qMakePair(property, property->name);
+ }
+
+ return rv;
+}
+
+/*!
+ \class QmlDomObject
+ \internal
+ \brief The QmlDomObject class represents an object instantiation.
+
+ Each object instantiated in a QML file has a corresponding QmlDomObject
+ node in the QML DOM.
+
+ In addition to the type information that determines the object to
+ instantiate, QmlDomObject's also have a set of associated QmlDomProperty's.
+ Each QmlDomProperty represents a QML property assignment on the instantiated
+ object. For example,
+
+ \qml
+QGraphicsWidget {
+ opacity: 0.5
+ size: "100x100"
+}
+ \endqml
+
+ describes a single QmlDomObject - "QGraphicsWidget" - with two properties,
+ "opacity" and "size". Obviously QGraphicsWidget has many more properties than just
+ these two, but the QML DOM representation only contains those assigned
+ values (or bindings) in the QML file.
+
+ The DOM tree can be modified to include new property assignments by calling
+ QmlDomObject::addProperty(). Existing property assignments can be modified
+ through the QmlDomProperty::setValue() method, or removed entirely by
+ calling QmlDomObject::removeProperty().
+*/
+
+/*!
+ Construct an invalid QmlDomObject.
+*/
+QmlDomObject::QmlDomObject()
+: d(new QmlDomObjectPrivate)
+{
+}
+
+/*!
+ Construct a new QmlDomObject with the specified \a objectType.
+*/
+QmlDomObject::QmlDomObject(const QByteArray &objectType)
+: d(new QmlDomObjectPrivate)
+{
+ Q_UNUSED(objectType);
+ qWarning("QmlDomObject::QmlDomObject(const QByteArray &): Not implemented");
+}
+
+/*!
+ Create a copy of \a other QmlDomObject.
+*/
+QmlDomObject::QmlDomObject(const QmlDomObject &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomObject.
+*/
+QmlDomObject::~QmlDomObject()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomObject.
+*/
+QmlDomObject &QmlDomObject::operator=(const QmlDomObject &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if this is a valid QmlDomObject, false otherwise.
+*/
+bool QmlDomObject::isValid() const
+{
+ return d->object != 0;
+}
+
+/*!
+ Returns the type name of this object.
+
+ For example, the type of this object would be "QGraphicsWidget".
+ \qml
+QGraphicsWidget { }
+ \endqml
+*/
+QByteArray QmlDomObject::objectType() const
+{
+ if (d->object) return d->object->typeName;
+ else return QByteArray();
+}
+
+/*!
+ Returns the QML id assigned to this object, or an empty QByteArray if no id
+ has been assigned.
+
+ For example, the object id of this object would be "MyText".
+ \qml
+Text { id: MyText }
+ \endqml
+*/
+QByteArray QmlDomObject::objectId() const
+{
+ if (d->object) return d->object->id;
+ else return QByteArray();
+}
+
+/*!
+ Set the object \a id. If any other object within the DOM tree has the same
+ id, the other object's id will be cleared.
+*/
+void QmlDomObject::setObjectId(const QByteArray &id)
+{
+ Q_UNUSED(id);
+ qWarning("QmlDomObject::setObjectId(const QByteArray &): Not implemented");
+}
+
+
+/*!
+ Returns the list of assigned properties on this object.
+
+ In the following example, "text" and "x" properties would be returned.
+ \qml
+Text {
+ text: "Hello world!"
+ x: 100
+}
+ \endqml
+*/
+QList<QmlDomProperty> QmlDomObject::properties() const
+{
+ QList<QmlDomProperty> rv;
+
+ if (!d->object)
+ return rv;
+
+ QmlDomObjectPrivate::Properties properties = d->properties();
+ for (int ii = 0; ii < properties.count(); ++ii) {
+
+ QmlDomProperty domProperty;
+ domProperty.d->property = properties.at(ii).first;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = properties.at(ii).second;
+ rv << domProperty;
+
+ }
+
+ if (d->object->defaultProperty) {
+ QmlDomProperty domProperty;
+ domProperty.d->property = d->object->defaultProperty;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = d->object->defaultProperty->name;
+ rv << domProperty;
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the object's \a name property if a value has been assigned to
+ it, or an invalid QmlDomProperty otherwise.
+
+ In the example below, \c {object.property("source")} would return a valid
+ QmlDomProperty, and \c {object.property("tile")} an invalid QmlDomProperty.
+
+ \qml
+Image { source: "sample.jpg" }
+ \endqml
+*/
+QmlDomProperty QmlDomObject::property(const QByteArray &name) const
+{
+ QList<QmlDomProperty> props = properties();
+ for (int ii = 0; ii < props.count(); ++ii)
+ if (props.at(ii).propertyName() == name)
+ return props.at(ii);
+ return QmlDomProperty();
+}
+
+/*!
+ Remove the property \a name from this object, if it exists. Otherwise does
+ nothing.
+*/
+void QmlDomObject::removeProperty(const QByteArray &name)
+{
+ Q_UNUSED(name);
+ qWarning("QmlDomObject::removeProperty(const QByteArray &): Not implemented");
+}
+
+/*!
+ Adds the property \a name with the specified \a value to this object. If
+ a property by \a name already exists, it will be removed.
+*/
+void QmlDomObject::addProperty(const QByteArray &name, const QmlDomValue &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+ qWarning("QmlDomObject::addProperty(const QByteArray &, const QmlDomValue &): Not implemented");
+}
+
+/*!
+ Returns true if this object is a custom type. Custom types are special
+ types that allow embeddeding non-QML data, such as SVG or HTML data,
+ directly into QML files.
+
+ \note Currently this method will always return false, and is a placekeeper
+ for future functionality.
+
+ \sa QmlDomObject::customTypeData()
+*/
+bool QmlDomObject::isCustomType() const
+{
+ return false;
+}
+
+/*!
+ Sets the custom type \a data. If this type is not a custom type, this
+ method does nothing.
+
+ \sa QmlDomObject::isCustomType() QmlDomObject::customTypeData()
+*/
+void QmlDomObject::setCustomTypeData(const QByteArray &data)
+{
+ Q_UNUSED(data);
+ qWarning("QmlDomObject::setCustomTypeData(const QByteArray &): Not implemented");
+}
+
+/*!
+ If this object represents a custom type, returns the data associated with
+ the custom type, otherwise returns an empty QByteArray().
+ QmlDomObject::isCustomType() can be used to check if this object represents
+ a custom type.
+*/
+QByteArray QmlDomObject::customTypeData() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns true if this object is a sub-component object. Sub-component
+ objects can be converted into QmlDomComponent instances by calling
+ QmlDomObject::toComponent().
+
+ \sa QmlDomObject::toComponent()
+*/
+bool QmlDomObject::isComponent() const
+{
+ return d->isVirtualComponent ||
+ (d->object && d->object->typeName == "Component");
+}
+
+/*!
+ Returns a QmlDomComponent for this object if it is a sub-component, or
+ an invalid QmlDomComponent if not. QmlDomObject::isComponent() can be used
+ to check if this object represents a sub-component.
+
+ \sa QmlDomObject::isComponent()
+*/
+QmlDomComponent QmlDomObject::toComponent() const
+{
+ QmlDomComponent rv;
+ if (isComponent())
+ rv.d = d;
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property assignment started
+, or 0 if the property is invalid.
+*/
+int QmlDomObject::position() const
+{
+ if (d && d->object)
+ return d->object->location.range.offset;
+ else
+ return 0;
+}
+
+/*!
+ Returns the length in the input data from where the property assignment star
+ted upto the end of it, or 0 if the property is invalid.
+*/
+int QmlDomObject::length() const
+{
+ if (d && d->object)
+ return d->object->location.range.length;
+ else
+ return 0;
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate()
+: value(0)
+{
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &other)
+: QSharedData(other), value(0)
+{
+ value = other.value;
+ if (value) value->addref();
+}
+
+QmlDomBasicValuePrivate::~QmlDomBasicValuePrivate()
+{
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValueLiteral
+ \internal
+ \brief The QmlDomValueLiteral class represents a literal value.
+
+ A literal value is a simple value, written inline with the QML. In the
+ example below, the "x", "y" and "color" properties are being assigned
+ literal values.
+
+ \qml
+Rect {
+ x: 10
+ y: 10
+ color: "red"
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral(const QmlDomValueLiteral &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::~QmlDomValueLiteral()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueLiteral.
+*/
+QmlDomValueLiteral &QmlDomValueLiteral::operator=(const QmlDomValueLiteral &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the literal value.
+
+ In the example below, the literal value will be the string "10".
+ \qml
+Rect { x: 10 }
+ \endqml
+*/
+QString QmlDomValueLiteral::literal() const
+{
+ if (d->value) return d->value->primitive();
+ else return QString();
+}
+
+/*!
+ Sets the literal \a value.
+*/
+void QmlDomValueLiteral::setLiteral(const QString &value)
+{
+ Q_UNUSED(value);
+ qWarning("QmlDomValueLiteral::setLiteral(const QString &): Not implemented");
+}
+
+/*!
+ \class QmlDomValueBinding
+ \internal
+ \brief The QmlDomValueBinding class represents a property binding.
+
+ A property binding is an ECMAScript expression assigned to a property. In
+ the example below, the "x" property is being assigned a property binding.
+
+ \qml
+Rect { x: Other.x }
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding(const QmlDomValueBinding &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueBinding.
+*/
+QmlDomValueBinding::~QmlDomValueBinding()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueBinding.
+*/
+QmlDomValueBinding &QmlDomValueBinding::operator=(const QmlDomValueBinding &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the binding expression.
+
+ In the example below, the string "Other.x" will be returned.
+ \qml
+Rect { x: Other.x }
+ \endqml
+*/
+QString QmlDomValueBinding::binding() const
+{
+ if (d->value)
+ return d->value->value.asScript();
+ else
+ return QString();
+}
+
+/*!
+ Sets the binding \a expression.
+*/
+void QmlDomValueBinding::setBinding(const QString &expression)
+{
+ Q_UNUSED(expression);
+ qWarning("QmlDomValueBinding::setBinding(const QString &): Not implemented");
+}
+
+/*!
+ \class QmlDomValueValueSource
+ \internal
+ \brief The QmlDomValueValueSource class represents a value source assignment value.
+
+ In QML, value sources are special value generating types that may be
+ assigned to properties. Value sources inherit the QmlPropertyValueSource
+ class. In the example below, the "x" property is being assigned the
+ NumericAnimation value source.
+
+ \qml
+Rect {
+ x: NumericAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource(const QmlDomValueValueSource &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::~QmlDomValueValueSource()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueValueSource.
+*/
+QmlDomValueValueSource &QmlDomValueValueSource::operator=(const QmlDomValueValueSource &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the value source object.
+
+ In the example below, an object representing the NumericAnimation will be
+ returned.
+ \qml
+Rect {
+ x: NumericAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomValueValueSource::object() const
+{
+ QmlDomObject rv;
+ if (d->value) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ Sets the value source \a object.
+*/
+void QmlDomValueValueSource::setObject(const QmlDomObject &object)
+{
+ Q_UNUSED(object);
+ qWarning("QmlDomValueValueSource::setObject(const QmlDomObject &): Not implemented");
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate()
+: property(0), value(0)
+{
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate(const QmlDomValuePrivate &other)
+: QSharedData(other), property(0), value(0)
+{
+ property = other.property;
+ value = other.value;
+ if (property) property->addref();
+ if (value) value->addref();
+}
+
+QmlDomValuePrivate::~QmlDomValuePrivate()
+{
+ if (property) property->release();
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValue
+ \internal
+ \brief The QmlDomValue class represents a generic Qml value.
+
+ QmlDomValue's can be assigned to QML \l {QmlDomProperty}{properties}. In
+ QML, properties can be assigned various different values, including basic
+ literals, property bindings, property value sources, objects and lists of
+ values. The QmlDomValue class allows a programmer to determine the specific
+ value type being assigned and access more detailed information through a
+ corresponding value type class.
+
+ For example, in the following example,
+
+ \qml
+Text {
+ text: "Hello World!"
+ y: Other.y
+}
+ \endqml
+
+ The text property is being assigned a literal, and the y property a property
+ binding. To output the values assigned to the text and y properties in the
+ above example from C++,
+
+ \code
+ QmlDomDocument document;
+ QmlDomObject root = document.rootObject();
+
+ QmlDomProperty text = root.property("text");
+ if (text.value().isLiteral()) {
+ QmlDomValueLiteral literal = text.value().toLiteral();
+ qDebug() << literal.literal();
+ }
+
+ QmlDomProperty y = root.property("y");
+ if (y.value().isBinding()) {
+ QmlDomValueBinding binding = y.value().toBinding();
+ qDebug() << binding.binding();
+ }
+ \endcode
+*/
+
+/*!
+ Construct an invalid QmlDomValue.
+*/
+QmlDomValue::QmlDomValue()
+: d(new QmlDomValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValue.
+*/
+QmlDomValue::QmlDomValue(const QmlDomValue &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValue
+*/
+QmlDomValue::~QmlDomValue()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValue.
+*/
+QmlDomValue &QmlDomValue::operator=(const QmlDomValue &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \enum QmlDomValue::Type
+
+ The type of the QmlDomValue node.
+
+ \value Invalid The QmlDomValue is invalid.
+ \value Literal The QmlDomValue is a literal value assignment. Use QmlDomValue::toLiteral() to access the type instance.
+ \value PropertyBinding The QmlDomValue is a property binding. Use QmlDomValue::toBinding() to access the type instance.
+ \value ValueSource The QmlDomValue is a property value source. Use QmlDomValue::toValueSource() to access the type instance.
+ \value Object The QmlDomValue is an object assignment. Use QmlDomValue::toObject() to access the type instnace.
+ \value List The QmlDomValue is a list of other values. Use QmlDomValue::toList() to access the type instance.
+*/
+
+/*!
+ Returns the type of this QmlDomValue.
+*/
+QmlDomValue::Type QmlDomValue::type() const
+{
+ if (d->property)
+ if (QmlMetaType::isList(d->property->type) ||
+ QmlMetaType::isQmlList(d->property->type) ||
+ (d->property && d->property->values.count() > 1))
+ return List;
+
+ QmlParser::Value *value = d->value;
+ if (!value && !d->property)
+ return Invalid;
+
+ switch(value->type) {
+ case QmlParser::Value::Unknown:
+ return Invalid;
+ case QmlParser::Value::Literal:
+ return Literal;
+ case QmlParser::Value::PropertyBinding:
+ return PropertyBinding;
+ case QmlParser::Value::ValueSource:
+ return ValueSource;
+ case QmlParser::Value::Component:
+ case QmlParser::Value::CreatedObject:
+ return Object;
+ case QmlParser::Value::SignalObject:
+ return Invalid;
+ case QmlParser::Value::SignalExpression:
+ return Literal;
+ case QmlParser::Value::Id:
+ return Literal;
+ }
+ return Invalid;
+}
+
+/*!
+ Returns true if this is an invalid value, otherwise false.
+*/
+bool QmlDomValue::isInvalid() const
+{
+ return type() == Invalid;
+}
+
+/*!
+ Returns true if this is a literal value, otherwise false.
+*/
+bool QmlDomValue::isLiteral() const
+{
+ return type() == Literal;
+}
+
+/*!
+ Returns true if this is a property binding value, otherwise false.
+*/
+bool QmlDomValue::isBinding() const
+{
+ return type() == PropertyBinding;
+}
+
+/*!
+ Returns true if this is a value source value, otherwise false.
+*/
+bool QmlDomValue::isValueSource() const
+{
+ return type() == ValueSource;
+}
+
+/*!
+ Returns true if this is an object value, otherwise false.
+*/
+bool QmlDomValue::isObject() const
+{
+ return type() == Object;
+}
+
+/*!
+ Returns true if this is a list value, otherwise false.
+*/
+bool QmlDomValue::isList() const
+{
+ return type() == List;
+}
+
+/*!
+ Returns a QmlDomValueLiteral if this value is a literal type, otherwise
+ returns an invalid QmlDomValueLiteral.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueLiteral QmlDomValue::toLiteral() const
+{
+ QmlDomValueLiteral rv;
+ if (type() == Literal) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueBinding if this value is a property binding type,
+ otherwise returns an invalid QmlDomValueBinding.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueBinding QmlDomValue::toBinding() const
+{
+ QmlDomValueBinding rv;
+ if (type() == PropertyBinding) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueValueSource if this value is a property value source
+ type, otherwise returns an invalid QmlDomValueValueSource.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueValueSource QmlDomValue::toValueSource() const
+{
+ QmlDomValueValueSource rv;
+ if (type() == ValueSource) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomObject if this value is an object assignment type, otherwise
+ returns an invalid QmlDomObject.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomObject QmlDomValue::toObject() const
+{
+ QmlDomObject rv;
+ if (type() == Object) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomList if this value is a list type, otherwise returns an
+ invalid QmlDomList.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomList QmlDomValue::toList() const
+{
+ QmlDomList rv;
+ if (type() == List) {
+ rv.d = d;
+ }
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property value startd, or 0
+ if the value is invalid.
+*/
+int QmlDomValue::position() const
+{
+ if (type() == Invalid)
+ return 0;
+ else
+ return d->value->location.range.offset;
+}
+
+/*!
+ Returns the length in the input data from where the property value started u
+pto the end of it, or 0 if the value is invalid.
+*/
+int QmlDomValue::length() const
+{
+ if (type() == Invalid)
+ return 0;
+ else
+ return d->value->location.range.length;
+}
+
+/*!
+ \class QmlDomList
+ \internal
+ \brief The QmlDomList class represents a list of values assigned to a QML property.
+
+ Lists of values can be assigned to properties. For example, the following
+ example assigns multiple objects to Item's "children" property
+ \qml
+Item {
+ children: [
+ Text { },
+ Rect { }
+ ]
+}
+ \endqml
+
+ Lists can also be implicitly created by assigning multiple
+ \l {QmlDomValueValueSource}{value sources} or constants to a property.
+ \qml
+Item {
+ x: 10
+ x: NumericAnimation {
+ running: false
+ from: 0
+ to: 100
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomList.
+*/
+QmlDomList::QmlDomList()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomList.
+*/
+QmlDomList::QmlDomList(const QmlDomList &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomList.
+*/
+QmlDomList::~QmlDomList()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomList.
+*/
+QmlDomList &QmlDomList::operator=(const QmlDomList &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the list of QmlDomValue's.
+*/
+QList<QmlDomValue> QmlDomList::values() const
+{
+ QList<QmlDomValue> rv;
+ if (!d->property)
+ return rv;
+
+ for (int ii = 0; ii < d->property->values.count(); ++ii) {
+ QmlDomValue v;
+ v.d->value = d->property->values.at(ii);
+ v.d->value->addref();
+ rv << v;
+ }
+
+ return rv;
+}
+
+/*!
+ Set the list of QmlDomValue's to \a values.
+*/
+void QmlDomList::setValues(const QList<QmlDomValue> &values)
+{
+ Q_UNUSED(values);
+ qWarning("QmlDomList::setValues(const QList<QmlDomValue> &): Not implemented");
+}
+
+/*!
+ Returns the position in the input data where the list started, or 0 if
+ the property is invalid.
+*/
+int QmlDomList::position() const
+{
+ if (d && d->property) {
+ return d->property->listValueRange.offset;
+ } else
+ return 0;
+}
+
+/*!
+ Returns the length in the input data from where the list started upto
+ the end of it, or 0 if the property is invalid.
+*/
+int QmlDomList::length() const
+{
+ if (d && d->property)
+ return d->property->listValueRange.length;
+ else
+ return 0;
+}
+
+
+/*!
+ \class QmlDomComponent
+ \internal
+ \brief The QmlDomComponent class represents sub-component within a QML document.
+
+ Sub-components are QmlComponents defined within a QML document. The
+ following example shows the definition of a sub-component with the id
+ "ListDelegate".
+
+ \qml
+Item {
+ Component {
+ id: ListDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+
+ Like QmlDomDocument's, components contain a single root object.
+*/
+
+/*!
+ Construct an empty QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent(const QmlDomComponent &other)
+: QmlDomObject(other)
+{
+}
+
+/*!
+ Destroy the QmlDomComponent.
+*/
+QmlDomComponent::~QmlDomComponent()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomComponent.
+*/
+QmlDomComponent &QmlDomComponent::operator=(const QmlDomComponent &other)
+{
+ static_cast<QmlDomObject &>(*this) = other;
+ return *this;
+}
+
+/*!
+ Returns the component's root object.
+
+ In the example below, the root object is the "Text" object.
+ \qml
+Item {
+ Component {
+ id: ListDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomComponent::componentRoot() const
+{
+ QmlDomObject rv;
+ if (d->isVirtualComponent) {
+ rv.d->object = d->object;
+ rv.d->object->addref();
+ } else if (d->object) {
+ QmlParser::Object *obj = 0;
+ if (d->object->defaultProperty &&
+ d->object->defaultProperty->values.count() == 1 &&
+ d->object->defaultProperty->values.at(0)->object)
+ obj = d->object->defaultProperty->values.at(0)->object;
+
+ if (obj) {
+ rv.d->object = obj;
+ rv.d->object->addref();
+ }
+ }
+
+ return rv;
+}
+
+/*!
+ Set the component's \a root object.
+*/
+void QmlDomComponent::setComponentRoot(const QmlDomObject &root)
+{
+ Q_UNUSED(root);
+ qWarning("QmlDomComponent::setComponentRoot(const QmlDomObject &): Not implemented");
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h
new file mode 100644
index 0000000..86eaecb
--- /dev/null
+++ b/src/declarative/qml/qmldom.h
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDOM_H
+#define QMLDOM_H
+
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QByteArray;
+class QmlDomObject;
+class QmlDomList;
+class QmlDomValue;
+class QmlEngine;
+class QmlDomComponent;
+class QIODevice;
+
+class QmlDomDocumentPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomDocument
+{
+public:
+ QmlDomDocument();
+ QmlDomDocument(const QmlDomDocument &);
+ ~QmlDomDocument();
+ QmlDomDocument &operator=(const QmlDomDocument &);
+
+ int version() const;
+ QList<QUrl> imports() const;
+
+ QList<QmlError> errors() const;
+ bool load(QmlEngine *, const QByteArray &, const QUrl & = QUrl());
+ QByteArray save() const;
+
+ QmlDomObject rootObject() const;
+private:
+ QSharedDataPointer<QmlDomDocumentPrivate> d;
+};
+
+class QmlDomPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomProperty
+{
+public:
+ QmlDomProperty();
+ QmlDomProperty(const QmlDomProperty &);
+ ~QmlDomProperty();
+ QmlDomProperty &operator=(const QmlDomProperty &);
+
+ QByteArray propertyName() const;
+ QList<QByteArray> propertyNameParts() const;
+
+ bool isDefaultProperty() const;
+
+ QmlDomValue value() const;
+ void setValue(const QmlDomValue &);
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomObject;
+ QSharedDataPointer<QmlDomPropertyPrivate> d;
+};
+
+class QmlDomObjectPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomObject
+{
+public:
+ QmlDomObject();
+ QmlDomObject(const QByteArray &);
+ QmlDomObject(const QmlDomObject &);
+ ~QmlDomObject();
+ QmlDomObject &operator=(const QmlDomObject &);
+
+ bool isValid() const;
+
+ QByteArray objectType() const;
+ QByteArray objectId() const;
+
+ void setObjectId(const QByteArray &);
+
+ QList<QmlDomProperty> properties() const;
+ QmlDomProperty property(const QByteArray &) const;
+
+ void removeProperty(const QByteArray &);
+ void addProperty(const QByteArray &, const QmlDomValue &);
+
+ bool isCustomType() const;
+ QByteArray customTypeData() const;
+ void setCustomTypeData(const QByteArray &);
+
+ bool isComponent() const;
+ QmlDomComponent toComponent() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomDocument;
+ friend class QmlDomComponent;
+ friend class QmlDomValue;
+ friend class QmlDomValueValueSource;
+ QSharedDataPointer<QmlDomObjectPrivate> d;
+};
+
+class QmlDomValuePrivate;
+class QmlDomBasicValuePrivate;
+class Q_DECLARATIVE_EXPORT QmlDomValueLiteral
+{
+public:
+ QmlDomValueLiteral();
+ QmlDomValueLiteral(const QmlDomValueLiteral &);
+ ~QmlDomValueLiteral();
+ QmlDomValueLiteral &operator=(const QmlDomValueLiteral &);
+
+ QString literal() const;
+ void setLiteral(const QString &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueBinding
+{
+public:
+ QmlDomValueBinding();
+ QmlDomValueBinding(const QmlDomValueBinding &);
+ ~QmlDomValueBinding();
+ QmlDomValueBinding &operator=(const QmlDomValueBinding &);
+
+ QString binding() const;
+ void setBinding(const QString &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueValueSource
+{
+public:
+ QmlDomValueValueSource();
+ QmlDomValueValueSource(const QmlDomValueValueSource &);
+ ~QmlDomValueValueSource();
+ QmlDomValueValueSource &operator=(const QmlDomValueValueSource &);
+
+ QmlDomObject object() const;
+ void setObject(const QmlDomObject &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomComponent : public QmlDomObject
+{
+public:
+ QmlDomComponent();
+ QmlDomComponent(const QmlDomComponent &);
+ ~QmlDomComponent();
+ QmlDomComponent &operator=(const QmlDomComponent &);
+
+ QmlDomObject componentRoot() const;
+ void setComponentRoot(const QmlDomObject &);
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValue
+{
+public:
+ enum Type {
+ Invalid,
+ Literal,
+ PropertyBinding,
+ ValueSource,
+ Object,
+ List
+ };
+
+ QmlDomValue();
+ QmlDomValue(const QmlDomValue &);
+ ~QmlDomValue();
+ QmlDomValue &operator=(const QmlDomValue &);
+
+ Type type() const;
+
+ bool isInvalid() const;
+ bool isLiteral() const;
+ bool isBinding() const;
+ bool isValueSource() const;
+ bool isObject() const;
+ bool isList() const;
+
+ QmlDomValueLiteral toLiteral() const;
+ QmlDomValueBinding toBinding() const;
+ QmlDomValueValueSource toValueSource() const;
+ QmlDomObject toObject() const;
+ QmlDomList toList() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomProperty;
+ friend class QmlDomList;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomList
+{
+public:
+ QmlDomList();
+ QmlDomList(const QmlDomList &);
+ ~QmlDomList();
+ QmlDomList &operator=(const QmlDomList &);
+
+ QList<QmlDomValue> values() const;
+ void setValues(const QList<QmlDomValue> &);
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_H
diff --git a/src/declarative/qml/qmldom_p.h b/src/declarative/qml/qmldom_p.h
new file mode 100644
index 0000000..74edd47
--- /dev/null
+++ b/src/declarative/qml/qmldom_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDOM_P_H
+#define QMLDOM_P_H
+
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+#include "qmlparser_p.h"
+
+class QmlDomDocumentPrivate : public QSharedData
+{
+public:
+ QmlDomDocumentPrivate();
+ QmlDomDocumentPrivate(const QmlDomDocumentPrivate &);
+ ~QmlDomDocumentPrivate();
+
+ QList<QmlError> errors;
+ QList<QUrl> imports;
+ QmlParser::Object *root;
+};
+
+class QmlDomObjectPrivate : public QSharedData
+{
+public:
+ QmlDomObjectPrivate();
+ QmlDomObjectPrivate(const QmlDomObjectPrivate &);
+ ~QmlDomObjectPrivate();
+
+ typedef QList<QPair<QmlParser::Property *, QByteArray> > Properties;
+ Properties properties() const;
+ Properties properties(QmlParser::Property *) const;
+
+ QmlParser::Object *object;
+ bool isVirtualComponent;
+};
+
+class QmlDomPropertyPrivate : public QSharedData
+{
+public:
+ QmlDomPropertyPrivate();
+ QmlDomPropertyPrivate(const QmlDomPropertyPrivate &);
+ ~QmlDomPropertyPrivate();
+
+ QByteArray propertyName;
+ QmlParser::Property *property;
+};
+
+class QmlDomValuePrivate : public QSharedData
+{
+public:
+ QmlDomValuePrivate();
+ QmlDomValuePrivate(const QmlDomValuePrivate &);
+ ~QmlDomValuePrivate();
+
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+};
+
+class QmlDomBasicValuePrivate : public QSharedData
+{
+public:
+ QmlDomBasicValuePrivate();
+ QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &);
+ ~QmlDomBasicValuePrivate();
+
+ QmlParser::Value *value;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_P_H
+
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
new file mode 100644
index 0000000..18f28ed
--- /dev/null
+++ b/src/declarative/qml/qmlengine.cpp
@@ -0,0 +1,1558 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QMetaProperty>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qobject_p.h>
+
+#ifdef QT_SCRIPTTOOLS_LIB
+#include <QScriptEngineDebugger>
+#endif
+
+#include <QScriptClass>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QNetworkAccessManager>
+#include <QList>
+#include <QPair>
+#include <QDebug>
+#include <QMetaObject>
+#include "qml.h"
+#include <qfxperf.h>
+#include <QStack>
+#include "private/qmlbasicscript_p.h"
+#include "private/qmlcompiledcomponent_p.h"
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qmlexpression.h"
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <qmlcomponent.h>
+#include "private/qmlmetaproperty_p.h"
+#include <private/qmlbindablevalue_p.h>
+
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER)
+
+Q_DECLARE_METATYPE(QmlMetaProperty)
+
+QML_DEFINE_TYPE(QObject,Object)
+
+static QScriptValue qmlMetaProperty_emit(QScriptContext *ctx, QScriptEngine *engine)
+{
+ QmlMetaProperty mp = qscriptvalue_cast<QmlMetaProperty>(ctx->thisObject());
+ if (mp.type() & QmlMetaProperty::Signal)
+ mp.emitSignal();
+ return engine->nullValue();
+}
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+
+struct QmlEngineStack {
+ QmlEngineStack();
+
+ QStack<QmlEngine *> mainThreadEngines;
+ QThread *mainThread;
+
+ QThreadStorage<QStack<QmlEngine *> *> storage;
+
+ QStack<QmlEngine *> *engines();
+};
+
+Q_GLOBAL_STATIC(QmlEngineStack, engineStack);
+
+QmlEngineStack::QmlEngineStack()
+: mainThread(0)
+{
+}
+
+QStack<QmlEngine *> *QmlEngineStack::engines()
+{
+ if (mainThread== 0) {
+ if (!QCoreApplication::instance())
+ return 0;
+ mainThread = QCoreApplication::instance()->thread();
+ }
+
+ // Note: This is very slightly faster than just using the thread storage
+ // for everything.
+ QStack<QmlEngine *> *engines = 0;
+ if (QThread::currentThread() == mainThread) {
+ engines = &mainThreadEngines;
+ } else {
+ engines = storage.localData();
+ if (!engines) {
+ engines = new QStack<QmlEngine *>;
+ storage.setLocalData(engines);
+ }
+ }
+ return engines;
+}
+
+
+QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
+: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
+ rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
+{
+ QScriptValue proto = scriptEngine.newObject();
+ proto.setProperty(QLatin1String("emit"),
+ scriptEngine.newFunction(qmlMetaProperty_emit));
+ scriptEngine.setDefaultPrototype(qMetaTypeId<QmlMetaProperty>(), proto);
+
+ QScriptValue qtObject = scriptEngine.newQMetaObject(StaticQtMetaObject::get());
+ scriptEngine.globalObject().setProperty(QLatin1String("Qt"), qtObject);
+}
+
+QmlEnginePrivate::~QmlEnginePrivate()
+{
+ delete rootContext;
+ rootContext = 0;
+ delete contextClass;
+ contextClass = 0;
+ delete objectClass;
+ objectClass = 0;
+ delete networkAccessManager;
+ networkAccessManager = 0;
+
+ for(int ii = 0; ii < bindValues.count(); ++ii)
+ clear(bindValues[ii]);
+ for(int ii = 0; ii < parserStatus.count(); ++ii)
+ clear(parserStatus[ii]);
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlBindableValue> &bvs)
+{
+ for (int ii = 0; ii < bvs.count; ++ii) {
+ QmlBindableValue *bv = bvs.at(ii);
+ if(bv) {
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bv));
+ p->mePtr = 0;
+ }
+ }
+ bvs.clear();
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss)
+{
+ for (int ii = 0; ii < pss.count; ++ii) {
+ QmlParserStatus *ps = pss.at(ii);
+ if(ps)
+ ps->d = 0;
+ }
+ pss.clear();
+}
+
+void QmlEnginePrivate::init()
+{
+ scriptEngine.installTranslatorFunctions();
+ contextClass = new QmlContextScriptClass(q);
+ objectClass = new QmlObjectScriptClass(q);
+ rootContext = new QmlContext(q);
+#ifdef QT_SCRIPTTOOLS_LIB
+ if (qmlDebugger()){
+ debugger = new QScriptEngineDebugger(q);
+ debugger->attachTo(&scriptEngine);
+ }
+#endif
+}
+
+QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c)
+{
+ QmlContext *old = currentBindContext;
+ currentBindContext = c;
+ return old;
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(QObject *obj, int n)
+: object(obj), notifyIndex(n)
+{
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
+: object(p.object()), name(p.name()), notifyIndex(p.property().notifySignalIndex())
+{
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(const CapturedProperty &o)
+: object(o.object), name(o.name), notifyIndex(o.notifyIndex)
+{
+}
+
+QmlEnginePrivate::CapturedProperty &
+QmlEnginePrivate::CapturedProperty::operator=(const CapturedProperty &o)
+{
+ object = o.object;
+ name = o.name;
+ notifyIndex = o.notifyIndex;
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
+Q_GLOBAL_STATIC(FunctionCache, functionCache);
+
+QScriptClass::QueryFlags
+QmlEnginePrivate::queryObject(const QString &propName,
+ uint *id, QObject *obj)
+{
+ QScriptClass::QueryFlags rv = 0;
+
+ QmlMetaProperty prop(obj, propName);
+ if (prop.type() == QmlMetaProperty::Invalid) {
+ QPair<const QMetaObject *, QString> key =
+ qMakePair(obj->metaObject(), propName);
+ bool isFunction = false;
+ if (functionCache()->contains(key)) {
+ isFunction = functionCache()->value(key);
+ } else {
+ QScriptValue sobj = scriptEngine.newQObject(obj);
+ QScriptValue func = sobj.property(propName);
+ isFunction = func.isFunction();
+ functionCache()->insert(key, isFunction);
+ }
+
+ if (isFunction) {
+ *id = QmlScriptClass::FunctionId;
+ rv |= QScriptClass::HandlesReadAccess;
+ }
+ } else {
+ *id = QmlScriptClass::PropertyId;
+ *id |= prop.save();
+
+ rv |= QScriptClass::HandlesReadAccess;
+ if (prop.isWritable())
+ rv |= QScriptClass::HandlesWriteAccess;
+ }
+
+ return rv;
+}
+
+QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
+ QObject *obj, uint id)
+{
+ if (id == QmlScriptClass::FunctionId) {
+ QScriptValue sobj = scriptEngine.newQObject(obj);
+ QScriptValue func = sobj.property(propName);
+ return func;
+ } else {
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+ if (!prop.isValid())
+ return QScriptValue();
+
+ if (prop.type() & QmlMetaProperty::Signal) {
+ return scriptEngine.newVariant(qVariantFromValue(prop));
+ } else {
+ QVariant var = prop.read();
+ if (prop.needsChangedNotifier())
+ capturedProperties << CapturedProperty(prop);
+ QObject *varobj = QmlMetaType::toQObject(var);
+ if (!varobj)
+ varobj = qvariant_cast<QObject *>(var);
+ if (varobj) {
+ return scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(varobj)));
+ } else {
+ if (var.type() == QVariant::Bool)
+ return QScriptValue(&scriptEngine, var.toBool());
+ return scriptEngine.newVariant(var);
+ }
+ }
+ }
+
+ return QScriptValue();
+}
+
+void QmlEnginePrivate::contextActivated(QmlContext *)
+{
+ Q_Q(QmlEngine);
+ QmlEngineStack *stack = engineStack();
+ if (!stack)
+ return;
+ QStack<QmlEngine *> *engines = stack->engines();
+ if (engines)
+ engines->push(q);
+}
+
+void QmlEnginePrivate::contextDeactivated(QmlContext *)
+{
+ QmlEngineStack *stack = engineStack();
+ if (!stack)
+ return;
+ QStack<QmlEngine *> *engines = stack->engines();
+ if (engines) {
+ Q_ASSERT(engines->top() == q_func());
+ engines->pop();
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////
+
+bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *obj)
+{
+ QmlMetaProperty prop(obj, propName);
+
+ if (!prop.isValid())
+ return false;
+
+ if (prop.needsChangedNotifier())
+ capturedProperties << CapturedProperty(prop);
+
+ if (prop.type() & QmlMetaProperty::Attached) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Attached;
+ cache.attached = prop.d->attachedObject();
+ return true;
+
+ } else if (prop.type() & QmlMetaProperty::Property) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Core;
+ cache.core = prop.property().propertyIndex();
+ cache.coreType = prop.propertyType();
+ return true;
+
+ } else if (prop.type() & QmlMetaProperty::SignalProperty) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::SignalProperty;
+ cache.core = prop.coreIndex();
+ return true;
+
+ } else if (prop.type() & QmlMetaProperty::Signal) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Signal;
+ cache.core = prop.coreIndex();
+ return true;
+
+ }
+
+ return false;
+}
+
+bool QmlEnginePrivate::loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context)
+{
+ while(context) {
+
+ QHash<QString, int>::ConstIterator iter =
+ context->propertyNames.find(propName);
+ if (iter != context->propertyNames.end()) {
+ cache.object = 0;
+ cache.type = QmlBasicScriptNodeCache::Variant;
+ cache.context = context;
+ cache.contextIndex = *iter;
+ capturedProperties << CapturedProperty(context->q_ptr, *iter + context->notifyIndex);
+ return true;
+ }
+
+ foreach(QObject *obj, context->defaultObjects) {
+ if (fetchCache(cache, propName, obj))
+ return true;
+ }
+
+ if (context->parent)
+ context = context->parent->d_func();
+ else
+ context = 0;
+ }
+ return false;
+}
+
+
+/*!
+ \class QmlEngine
+ \brief The QmlEngine class provides an environment for instantiating QML components.
+ \mainclass
+
+ Each QML component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are arranged
+ hierarchically and this hierarchy is managed by the QmlEngine.
+
+ Prior to creating any QML components, an application must have created a
+ QmlEngine to gain access to a QML context. The following example shows how
+ to create a simple Text item.
+
+ \code
+ QmlEngine engine;
+ QmlComponent component(&engine, "Text { text: \"Hello world!\" }");
+ QFxItem *item = qobject_cast<QFxItem *>(component.create());
+
+ //add item to view, etc
+ ...
+ \endcode
+
+ In this case, the Text item will be created in the engine's
+ \l {QmlEngine::rootContext()}{root context}.
+
+ \sa QmlComponent QmlContext
+*/
+
+/*!
+ Create a new QmlEngine with the given \a parent.
+*/
+QmlEngine::QmlEngine(QObject *parent)
+: QObject(*new QmlEnginePrivate(this), parent)
+{
+ Q_D(QmlEngine);
+ d->init();
+
+ qRegisterMetaType<QVariant>("QVariant");
+}
+
+/*!
+ Destroys the QmlEngine.
+
+ Any QmlContext's created on this engine will be invalidated, but not
+ destroyed (unless they are parented to the QmlEngine object).
+*/
+QmlEngine::~QmlEngine()
+{
+}
+
+/*!
+ Clears the engine's internal component cache.
+
+ Normally the QmlEngine caches components loaded from qml files. This method
+ clears this cache and forces the component to be reloaded.
+ */
+void QmlEngine::clearComponentCache()
+{
+ Q_D(QmlEngine);
+ d->typeManager.clearCache();
+}
+
+/*!
+ Returns the engine's root context.
+
+ The root context is automatically created by the QmlEngine. Data that
+ should be available to all QML component instances instantiated by the
+ engine should be put in the root context.
+
+ Additional data that should only be available to a subset of component
+ instances should be added to sub-contexts parented to the root context.
+*/
+QmlContext *QmlEngine::rootContext()
+{
+ Q_D(QmlEngine);
+ return d->rootContext;
+}
+
+/*!
+ Returns this engine's active context, or 0 if no context is active on this
+ engine.
+
+ Contexts are activated and deactivated by calling QmlContext::activate() and
+ QmlContext::deactivate() respectively.
+
+ Context activation holds no special semantic, other than it allows types
+ instantiated by QML to access "their" context without having it passed as
+ a parameter in their constructor, as shown below.
+ \code
+ class MyClass : ... {
+ ...
+ MyClass() {
+ qWarning() << "I was instantiated in this context:"
+ << QmlContext::activeContext();
+ }
+ };
+ \endcode
+*/
+QmlContext *QmlEngine::activeContext()
+{
+ Q_D(QmlEngine);
+ if (d->currentBindContext)
+ return d->currentBindContext;
+ else
+ return 0;
+}
+
+/*!
+ Sets the mappings from namespace URIs to URL to \a map.
+
+ \sa nameSpacePaths()
+*/
+void QmlEngine::setNameSpacePaths(const QMap<QString,QString>& map)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths = map;
+}
+
+/*!
+ Adds mappings (given by \a map) from namespace URIs to URL.
+
+ \sa nameSpacePaths()
+*/
+void QmlEngine::addNameSpacePaths(const QMap<QString,QString>& map)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths.unite(map);
+}
+
+/*!
+ Adds a mapping from namespace URI \a ns to URL \a path.
+
+ \sa nameSpacePaths()
+*/
+void QmlEngine::addNameSpacePath(const QString& ns, const QString& path)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths.insertMulti(ns,path);
+}
+
+/*!
+ Returns the mapping from namespace URIs to URLs.
+
+ Currently, only the empty namespace is supported
+ (i.e. types cannot be qualified with a namespace).
+
+ The QML \c import statement can be used to import a directory of
+ components into the empty namespace.
+
+ \qml
+ import "MyModuleDirectory"
+ \endqml
+
+ This is also possible from C++:
+
+ \code
+ engine->addNameSpacePath("","file:///opt/abcdef");
+ \endcode
+
+ \sa componentUrl()
+*/
+QMap<QString,QString> QmlEngine::nameSpacePaths() const
+{
+ Q_D(const QmlEngine);
+ return d->nameSpacePaths;
+}
+
+/*!
+ Returns the URL for the component source \a src, as mapped
+ by the nameSpacePaths(), resolved relative to \a baseUrl.
+
+ \sa nameSpacePaths()
+*/
+QUrl QmlEngine::componentUrl(const QUrl& src, const QUrl& baseUrl) const
+{
+ Q_D(const QmlEngine);
+
+ // Find the most-specific namespace matching src.
+ // For files, multiple paths can be given, the first found is used.
+ QUrl r;
+ QMap<QString, QString>::const_iterator i = d->nameSpacePaths.constBegin();
+ QString rns=QLatin1String(":"); // ns of r, if file found, initial an imposible namespace
+ QString srcstring = src.toString();
+ while (i != d->nameSpacePaths.constEnd()) {
+ QString ns = i.key();
+ QString path = i.value();
+ if (ns != rns) {
+ if (srcstring.startsWith(ns) && (ns.length()==0 || srcstring[ns.length()]==QLatin1Char('/'))) {
+ QString file = ns.length()==0 ? srcstring : srcstring.mid(ns.length()+1);
+ QUrl cr = baseUrl.resolved(QUrl(path + QLatin1String("/") + file));
+ QString lf = cr.toLocalFile();
+ if (lf.isEmpty() || QFile::exists(lf)) {
+ r = cr;
+ rns = ns;
+ }
+ }
+ }
+ ++i;
+ }
+ if (r.isEmpty())
+ r = baseUrl.resolved(src);
+ return r;
+}
+
+/*!
+ Returns the list of base urls the engine browses to find sub-components.
+
+ The search path consists of the base of the \a url, and, in the case of local files,
+ the directories imported using the "import" statement in \a qml.
+ */
+QList<QUrl> QmlEngine::componentSearchPath(const QByteArray &qml, const QUrl &url) const
+{
+ QList<QUrl> searchPath;
+
+ searchPath << url.resolved(QUrl(QLatin1String(".")));
+
+ if (QFileInfo(url.toLocalFile()).exists()) {
+ QmlScriptParser parser;
+ if (parser.parse(qml, url)) {
+ for (int i = 0; i < parser.imports().size(); ++i) {
+ QUrl importUrl = QUrl(parser.imports().at(i).uri);
+ if (importUrl.isRelative()) {
+ searchPath << url.resolved(importUrl);
+ } else {
+ searchPath << importUrl;
+ }
+ }
+ }
+ }
+
+ return searchPath;
+}
+
+/*!
+ Sets the common QNetworkAccessManager, \a network, used by all QML elements instantiated
+ by this engine.
+
+ Any previously set manager is deleted and \a network is owned by the QmlEngine. This
+ method should only be called before any QmlComponents are instantiated.
+*/
+void QmlEngine::setNetworkAccessManager(QNetworkAccessManager *network)
+{
+ Q_D(QmlEngine);
+ delete d->networkAccessManager;
+ d->networkAccessManager = network;
+}
+
+/*!
+ Returns the common QNetworkAccessManager used by all QML elements
+ instantiated by this engine.
+
+ The default implements no caching, cookiejar, etc., just a default
+ QNetworkAccessManager.
+*/
+QNetworkAccessManager *QmlEngine::networkAccessManager() const
+{
+ Q_D(const QmlEngine);
+ if (!d->networkAccessManager)
+ d->networkAccessManager = new QNetworkAccessManager;
+ return d->networkAccessManager;
+}
+
+/*!
+ Returns the QmlContext for the \a object, or 0 if no context has been set.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+QmlContext *QmlEngine::contextForObject(const QObject *object)
+{
+ if(!object)
+ return 0;
+
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+
+ QmlSimpleDeclarativeData *data =
+ static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData);
+
+ return data?data->context:0;
+}
+
+/*!
+ Sets the QmlContext for the \a object to \a context.
+ If the \a object already has a context, a warning is
+ output, but the context is not changed.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+void QmlEngine::setContextForObject(QObject *object, QmlContext *context)
+{
+ QObjectPrivate *priv = QObjectPrivate::get(object);
+
+ QmlSimpleDeclarativeData *data =
+ static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData);
+
+ if (data && data->context) {
+ qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext");
+ return;
+ }
+
+ if (!data) {
+ priv->declarativeData = &context->d_func()->contextData;
+ } else {
+ data->context = context;
+ }
+
+ context->d_func()->contextObjects.append(object);
+}
+
+QmlContext *qmlContext(const QObject *obj)
+{
+ return QmlEngine::contextForObject(obj);
+}
+
+QmlEngine *qmlEngine(const QObject *obj)
+{
+ QmlContext *context = QmlEngine::contextForObject(obj);
+ return context?context->engine():0;
+}
+
+QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object)
+{
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+
+
+ QmlSimpleDeclarativeData *data = static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData);
+
+ QmlExtendedDeclarativeData *edata = (data && data->flags & QmlSimpleDeclarativeData::Extended)?static_cast<QmlExtendedDeclarativeData *>(data):0;
+
+ if (edata) {
+ QObject *rv = edata->attachedProperties.value(id);
+ if (rv)
+ return rv;
+ }
+
+ QmlAttachedPropertiesFunc pf = QmlMetaType::attachedPropertiesFuncById(id);
+ if (!pf)
+ return 0;
+
+ QObject *rv = pf(const_cast<QObject *>(object));
+
+ if (rv) {
+ if (!edata) {
+
+ edata = new QmlExtendedDeclarativeData;
+ if (data) edata->context = data->context;
+ priv->declarativeData = edata;
+
+ }
+
+ edata->attachedProperties.insert(id, rv);
+ }
+
+ return rv;
+}
+
+void QmlSimpleDeclarativeData::destroyed(QObject *object)
+{
+ if (context)
+ context->d_func()->contextObjects.removeAll(object);
+}
+
+void QmlExtendedDeclarativeData::destroyed(QObject *object)
+{
+ QmlSimpleDeclarativeData::destroyed(object);
+ delete this;
+}
+
+/*! \internal */
+QScriptEngine *QmlEngine::scriptEngine()
+{
+ Q_D(QmlEngine);
+ return &d->scriptEngine;
+}
+
+/*!
+ Returns the currently active QmlEngine.
+
+ The active engine is the engine associated with the last activated
+ QmlContext. This method is thread-safe - the "active" engine is maintained
+ independently for each thread.
+*/
+QmlEngine *QmlEngine::activeEngine()
+{
+ QmlEngineStack *stack = engineStack();
+ if (!stack) return 0;
+
+ QStack<QmlEngine *> *engines = stack->engines();
+ if (!engines) {
+ qWarning("QmlEngine::activeEngine() cannot be called before the construction of QCoreApplication");
+ return 0;
+ }
+
+ if (engines->isEmpty())
+ return 0;
+ else
+ return engines->top();
+}
+
+
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b)
+: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), line(-1), id(0), log(0)
+{
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc)
+: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), line(-1), id(0), log(0)
+{
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr)
+: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), line(-1), id(0), log(0)
+{
+}
+
+QmlExpressionPrivate::~QmlExpressionPrivate()
+{
+ sse.deleteScriptState(sseData);
+ sseData = 0;
+ delete proxy;
+ delete log;
+}
+
+/*!
+ Create an invalid QmlExpression.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+ */
+QmlExpression::QmlExpression()
+: d(new QmlExpressionPrivate(this))
+{
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
+ QmlRefCount *rc, QObject *me)
+: d(new QmlExpressionPrivate(this, expr, rc))
+{
+ d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
+ d->me = me;
+}
+
+/*!
+ Create a QmlExpression object.
+
+ The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
+ QObject *scope)
+: d(new QmlExpressionPrivate(this, expression))
+{
+ d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
+ d->me = scope;
+}
+
+/*!
+ Destroy the QmlExpression instance.
+*/
+QmlExpression::~QmlExpression()
+{
+ if (d->ctxt)
+ d->ctxt->d_func()->childExpressions.remove(this);
+ delete d; d = 0;
+}
+
+/*!
+ Returns the QmlEngine this expression is associated with, or 0 if there
+ is no association or the QmlEngine has been destroyed.
+*/
+QmlEngine *QmlExpression::engine() const
+{
+ return d->ctxt?d->ctxt->engine():0;
+}
+
+/*!
+ Returns the QmlContext this expression is associated with, or 0 if there
+ is no association or the QmlContext has been destroyed.
+*/
+QmlContext *QmlExpression::context() const
+{
+ return d->ctxt;
+}
+
+/*!
+ Returns the expression string.
+*/
+QString QmlExpression::expression() const
+{
+ if (d->sse.isValid())
+ return QLatin1String(d->sse.expression());
+ else
+ return d->expression;
+}
+
+/*!
+ Clear the expression.
+*/
+void QmlExpression::clearExpression()
+{
+ setExpression(QString());
+}
+
+/*!
+ Set the expression to \a expression.
+*/
+void QmlExpression::setExpression(const QString &expression)
+{
+ if (d->sseData) {
+ d->sse.deleteScriptState(d->sseData);
+ d->sseData = 0;
+ }
+
+ delete d->proxy; d->proxy = 0;
+
+ d->expression = expression;
+
+ d->sse.clear();
+}
+
+/*!
+ Called by QmlExpression each time the expression value changes from the
+ last time it was evaluated. The expression must have been evaluated at
+ least once (by calling QmlExpression::value()) before this callback will
+ be made.
+
+ The default implementation does nothing.
+*/
+void QmlExpression::valueChanged()
+{
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+void BindExpressionProxy::changed()
+{
+ e->valueChanged();
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+*/
+QVariant QmlExpression::value()
+{
+ QVariant rv;
+ if (!d->ctxt || !engine() || (!d->sse.isValid() && d->expression.isEmpty()))
+ return rv;
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValue> perf;
+#endif
+
+ QmlBasicScript::CacheState cacheState = QmlBasicScript::Reset;
+
+ QmlEnginePrivate *ep = engine()->d_func();
+ QmlExpression *lastCurrentExpression = ep->currentExpression;
+ ep->currentExpression = this;
+ if (d->sse.isValid()) {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueSSE> perfsse;
+#endif
+
+ context()->d_func()->defaultObjects.insert(context()->d_func()->highPriorityCount, d->me);
+
+ if (!d->sseData)
+ d->sseData = d->sse.newScriptState();
+ rv = d->sse.run(context(), d->sseData, &cacheState);
+
+ context()->d_func()->defaultObjects.removeAt(context()->d_func()->highPriorityCount);
+ } else {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
+#endif
+ context()->d_func()->defaultObjects.insert(context()->d_func()->highPriorityCount, d->me);
+
+ QScriptEngine *scriptEngine = engine()->scriptEngine();
+ QScriptValueList oldScopeChain = scriptEngine->currentContext()->scopeChain();
+ for (int i = 0; i < oldScopeChain.size(); ++i) {
+ scriptEngine->currentContext()->popScope();
+ }
+ for (int i = context()->d_func()->scopeChain.size() - 1; i > -1; --i) {
+ scriptEngine->currentContext()->pushScope(context()->d_func()->scopeChain.at(i));
+ }
+ QScriptValue svalue = scriptEngine->evaluate(expression(), d->fileName, d->line);
+ if (scriptEngine->hasUncaughtException()) {
+ if (scriptEngine->uncaughtException().isError()){
+ QScriptValue exception = scriptEngine->uncaughtException();
+ if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
+ qWarning() << exception.property(QLatin1String("fileName")).toString()
+ << scriptEngine->uncaughtExceptionLineNumber()
+ << exception.toString();
+
+ } else {
+ qWarning() << exception.toString();
+ }
+ }
+ }
+
+ context()->d_func()->defaultObjects.removeAt(context()->d_func()->highPriorityCount);
+ if (svalue.isArray()) {
+ int length = svalue.property(QLatin1String("length")).toInt32();
+ if (length && svalue.property(0).isObject()) {
+ QList<QObject *> list;
+ for (int ii = 0; ii < length; ++ii) {
+ QScriptValue arrayItem = svalue.property(ii);
+ QObject *d = qvariant_cast<QObject *>(arrayItem.data().toVariant());
+ if (d) {
+ list << d;
+ } else {
+ list << 0;
+ }
+ }
+ rv = QVariant::fromValue(list);
+ }
+ } else if (svalue.isObject()) {
+ QScriptValue objValue = svalue.data();
+ if (objValue.isValid())
+ rv = objValue.toVariant();
+ }
+ if (rv.isNull()) {
+ rv = svalue.toVariant();
+ }
+
+ for (int i = 0; i < context()->d_func()->scopeChain.size(); ++i) {
+ scriptEngine->currentContext()->popScope();
+ }
+ for (int i = oldScopeChain.size() - 1; i > -1; --i) {
+ scriptEngine->currentContext()->pushScope(oldScopeChain.at(i));
+ }
+ }
+ ep->currentExpression = lastCurrentExpression;
+
+ if (cacheState != QmlBasicScript::NoChange) {
+ if (cacheState != QmlBasicScript::Incremental && d->proxy) {
+ delete d->proxy;
+ d->proxy = 0;
+ }
+
+ if (trackChange() && ep->capturedProperties.count()) {
+ if (!d->proxy)
+ d->proxy = new BindExpressionProxy(this);
+
+ static int changedIndex = -1;
+ if (changedIndex == -1)
+ changedIndex = BindExpressionProxy::staticMetaObject.indexOfSlot("changed()");
+
+ if(qmlDebugger()) {
+ QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
+ log.setExpression(expression());
+ log.setResult(rv);
+
+ for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) {
+ const QmlEnginePrivate::CapturedProperty &prop =
+ ep->capturedProperties.at(ii);
+
+ if (prop.notifyIndex != -1) {
+ QMetaObject::connect(prop.object, prop.notifyIndex,
+ d->proxy, changedIndex);
+ } else {
+ QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object->metaObject()->className()) + QLatin1String("].") + prop.name;
+ log.addWarning(warn);
+ }
+ }
+ d->addLog(log);
+
+ } else {
+ for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) {
+ const QmlEnginePrivate::CapturedProperty &prop =
+ ep->capturedProperties.at(ii);
+
+ if (prop.notifyIndex != -1)
+ QMetaObject::connect(prop.object, prop.notifyIndex,
+ d->proxy, changedIndex);
+ }
+ }
+ } else {
+ QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
+ log.setExpression(expression());
+ log.setResult(rv);
+ d->addLog(log);
+ }
+
+ } else {
+ if(qmlDebugger()) {
+ QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
+ log.setExpression(expression());
+ log.setResult(rv);
+ d->addLog(log);
+ }
+ }
+
+ ep->capturedProperties.clear();
+
+ return rv;
+}
+
+/*!
+ Returns true if the expression results in a constant value.
+ QmlExpression::value() must have been invoked at least once before the
+ return from this method is valid.
+ */
+bool QmlExpression::isConstant() const
+{
+ return d->proxy == 0;
+}
+
+/*!
+ Returns true if the changes are tracked in the expression's value.
+*/
+bool QmlExpression::trackChange() const
+{
+ return d->trackChange;
+}
+
+/*!
+ Set whether changes are tracked in the expression's value to \a trackChange.
+
+ If true, the QmlExpression will monitor properties involved in the
+ expression's evaluation, and call QmlExpression::valueChanged() if they have
+ changed. This allows an application to ensure that any value associated
+ with the result of the expression remains up to date.
+
+ If false, the QmlExpression will not montitor properties involved in the
+ expression's evaluation, and QmlExpression::valueChanged() will never be
+ called. This is more efficient if an application wants a "one off"
+ evaluation of the expression.
+
+ By default, trackChange is true.
+*/
+void QmlExpression::setTrackChange(bool trackChange)
+{
+ d->trackChange = trackChange;
+}
+
+/*!
+ Set the location of this expression to \a line of \a fileName. This information
+ is used by the script engine.
+*/
+void QmlExpression::setSourceLocation(const QString &fileName, int line)
+{
+ d->fileName = fileName;
+ d->line = line;
+}
+
+/*!
+ Returns the expression's scope object, if provided, otherwise 0.
+
+ In addition to data provided by the expression's QmlContext, the scope
+ object's properties are also in scope during the expression's evaluation.
+*/
+QObject *QmlExpression::scopeObject() const
+{
+ return d->me;
+}
+
+/*!
+ \internal
+*/
+quint32 QmlExpression::id() const
+{
+ return d->id;
+}
+
+/*!
+ \class QmlExpression
+ \brief The QmlExpression class evaluates ECMAScript in a QML context.
+*/
+
+/*!
+ \class QmlExpressionObject
+ \brief The QmlExpressionObject class extends QmlExpression with signals and slots.
+
+ To remain as lightweight as possible, QmlExpression does not inherit QObject
+ and consequently cannot use signals or slots. For the cases where this is
+ more convenient in an application, QmlExpressionObject can be used instead.
+
+ QmlExpressionObject behaves identically to QmlExpression, except that the
+ QmlExpressionObject::value() method is a slot, and the
+ QmlExpressionObject::valueChanged() callback is a signal.
+*/
+/*!
+ Create a QmlExpression with the specified \a parent.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+*/
+QmlExpressionObject::QmlExpressionObject(QObject *parent)
+: QObject(parent)
+{
+}
+
+/*!
+ Create a QmlExpressionObject with the specified \a parent.
+
+ The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, const QString &expression, QObject *scope, QObject *parent)
+: QObject(parent), QmlExpression(ctxt, expression, scope)
+{
+}
+
+/*! \internal */
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, void *d, QmlRefCount *rc, QObject *me)
+: QmlExpression(ctxt, d, rc, me)
+{
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+*/
+QVariant QmlExpressionObject::value()
+{
+ return QmlExpression::value();
+}
+
+/*!
+ \fn void QmlExpressionObject::valueChanged()
+
+ Emitted each time the expression value changes from the last time it was
+ evaluated. The expression must have been evaluated at least once (by
+ calling QmlExpressionObject::value()) before this signal will be emitted.
+*/
+
+QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
+: QScriptClass(bindengine->scriptEngine()), engine(bindengine)
+{
+}
+
+/////////////////////////////////////////////////////////////
+/*
+ The QmlContextScriptClass handles property access for a QmlContext
+ via QtScript.
+ */
+QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
+ : QmlScriptClass(bindEngine)
+{
+}
+
+QmlContextScriptClass::~QmlContextScriptClass()
+{
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(flags);
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+ QueryFlags rv = 0;
+
+ QString propName = name.toString();
+
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Query Context:" << propName << bindContext;
+#endif
+
+ *id = InvalidId;
+ if (bindContext->d_func()->propertyNames.contains(propName)) {
+ rv |= HandlesReadAccess;
+ *id = VariantPropertyId;
+ }
+
+ for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
+ rv = engine->d_func()->queryObject(propName, id,
+ bindContext->d_func()->defaultObjects.at(ii));
+ if (rv)
+ *id |= (ii << 24);
+ }
+
+ return rv;
+}
+
+QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Context Property:" << propName << bindContext;
+#endif
+
+ uint basicId = id & QmlScriptClass::ClassIdMask;
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+
+ switch (basicId) {
+ case VariantPropertyId:
+ {
+ QString propName = name.toString();
+ int index = bindContext->d_func()->propertyNames.value(propName);
+ QVariant value = bindContext->d_func()->propertyValues.at(index);
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Context Property: Resolved property" << propName
+ << "to context variant property list" << bindContext <<". Value:" << rv.toVariant();
+#endif
+ QScriptValue rv;
+ if (QmlMetaType::isObject(value.userType())) {
+ rv = scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newVariant(value));
+ } else {
+ rv = scriptEngine->newVariant(value);
+ }
+ engine->d_func()->capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, index + bindContext->d_func()->notifyIndex);
+ return rv;
+ }
+ default:
+ {
+ int objId = (id & ClassIdSelectorMask) >> 24;
+ QObject *obj = bindContext->d_func()->defaultObjects.at(objId);
+ QScriptValue rv = engine->d_func()->propertyObject(name, obj,
+ id & ~QmlScriptClass::ClassIdSelectorMask);
+ if (rv.isValid()) {
+#ifdef PROPERTY_DEBUG
+ qWarning() << "~Property: Resolved property" << propName
+ << "to context default object" << bindContext << obj <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+ break;
+ }
+ }
+
+ return QScriptValue();
+}
+
+void QmlContextScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Set QmlObject Property" << name.toString() << value.toVariant();
+#endif
+
+ int objIdx = (id & QmlScriptClass::ClassIdSelectorMask) >> 24;
+ QObject *obj = bindContext->d_func()->defaultObjects.at(objIdx);
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue oldact = scriptEngine->currentContext()->activationObject();
+ scriptEngine->currentContext()->setActivationObject(scriptEngine->globalObject());
+
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+
+ QVariant v;
+ QObject *data = value.data().toQObject();
+ if (data) {
+ v = QVariant::fromValue(data);
+ } else {
+ v = value.toVariant();
+ }
+ prop.write(v);
+
+ scriptEngine->currentContext()->setActivationObject(oldact);
+}
+
+/////////////////////////////////////////////////////////////
+/*
+ The QmlObjectScriptClass handles property access for QObjects
+ via QtScript.
+ */
+QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
+ : QmlScriptClass(bindEngine)
+{
+ engine = bindEngine;
+}
+
+QmlObjectScriptClass::~QmlObjectScriptClass()
+{
+}
+
+QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(flags);
+ QObject *obj = object.data().toQObject();
+ QueryFlags rv = 0;
+ QString propName = name.toString();
+
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Query QmlObject:" << propName << obj;
+#endif
+
+ if (obj)
+ rv = engine->d_func()->queryObject(propName, id, obj);
+
+ return rv;
+}
+
+QScriptValue QmlObjectScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+ QObject *obj = object.data().toQObject();
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "QmlObject Property:" << propName << obj;
+#endif
+
+ QScriptValue rv = engine->d_func()->propertyObject(name, obj, id);
+ if (rv.isValid()) {
+#ifdef PROPERTY_DEBUG
+ qWarning() << "~Property: Resolved property" << propName
+ << "to object" << obj <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+
+ return QScriptValue();
+}
+
+void QmlObjectScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+ QObject *obj = object.data().toQObject();
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Set QmlObject Property" << name.toString() << value.toVariant();
+#endif
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue oldact = scriptEngine->currentContext()->activationObject();
+ scriptEngine->currentContext()->setActivationObject(scriptEngine->globalObject());
+
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+
+ QVariant v;
+ QObject *data = value.data().toQObject();
+ if (data) {
+ v = QVariant::fromValue(data);
+ } else {
+ v = value.toVariant();
+ }
+ prop.write(v);
+
+ scriptEngine->currentContext()->setActivationObject(oldact);
+}
+
+void QmlExpressionPrivate::addLog(const QmlExpressionLog &l)
+{
+ if (!log)
+ log = new QList<QmlExpressionLog>();
+ log->append(l);
+}
+
+QmlExpressionLog::QmlExpressionLog()
+{
+}
+
+QmlExpressionLog::QmlExpressionLog(const QmlExpressionLog &o)
+: m_time(o.m_time),
+ m_expression(o.m_expression),
+ m_result(o.m_result),
+ m_warnings(o.m_warnings)
+{
+}
+
+QmlExpressionLog::~QmlExpressionLog()
+{
+}
+
+QmlExpressionLog &QmlExpressionLog::operator=(const QmlExpressionLog &o)
+{
+ m_time = o.m_time;
+ m_expression = o.m_expression;
+ m_result = o.m_result;
+ m_warnings = o.m_warnings;
+ return *this;
+}
+
+void QmlExpressionLog::setTime(quint32 time)
+{
+ m_time = time;
+}
+
+quint32 QmlExpressionLog::time() const
+{
+ return m_time;
+}
+
+QString QmlExpressionLog::expression() const
+{
+ return m_expression;
+}
+
+void QmlExpressionLog::setExpression(const QString &e)
+{
+ m_expression = e;
+}
+
+QStringList QmlExpressionLog::warnings() const
+{
+ return m_warnings;
+}
+
+void QmlExpressionLog::addWarning(const QString &w)
+{
+ m_warnings << w;
+}
+
+QVariant QmlExpressionLog::result() const
+{
+ return m_result;
+}
+
+void QmlExpressionLog::setResult(const QVariant &r)
+{
+ m_result = r;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
new file mode 100644
index 0000000..9382389
--- /dev/null
+++ b/src/declarative/qml/qmlengine.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLENGINE_H
+#define QMLENGINE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmap.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlComponent;
+class QmlEnginePrivate;
+class QmlExpression;
+class QmlContext;
+class QUrl;
+class QScriptEngine;
+class QNetworkAccessManager;
+class Q_DECLARATIVE_EXPORT QmlEngine : public QObject
+{
+ Q_OBJECT
+public:
+ QmlEngine(QObject *p = 0);
+ virtual ~QmlEngine();
+
+ static QmlEngine *activeEngine();
+
+ QmlContext *rootContext();
+ QmlContext *activeContext();
+
+ void clearComponentCache();
+
+ void setNameSpacePaths(const QMap<QString,QString>& map);
+ void addNameSpacePaths(const QMap<QString,QString>& map);
+ void addNameSpacePath(const QString&,const QString&);
+ QMap<QString,QString> nameSpacePaths() const;
+ QUrl componentUrl(const QUrl& src, const QUrl& baseUrl) const;
+
+ QList<QUrl> componentSearchPath(const QByteArray &qml, const QUrl &url) const;
+
+ void setNetworkAccessManager(QNetworkAccessManager *);
+ QNetworkAccessManager *networkAccessManager() const;
+
+ static QmlContext *contextForObject(const QObject *);
+ static void setContextForObject(QObject *, QmlContext *);
+private:
+ // LK: move to the private class
+ QScriptEngine *scriptEngine();
+ friend class QFxItem; // XXX
+ friend class QmlScriptPrivate;
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+ friend class QmlScriptClass;
+ friend class QmlContext;
+ friend class QmlContextPrivate;
+ friend class QmlExpression;
+ friend class QmlBasicScript;
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlContextScriptClass; //###
+ friend class QmlObjectScriptClass; //###
+ Q_DECLARE_PRIVATE(QmlEngine)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLENGINE_H
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
new file mode 100644
index 0000000..89b0a4a
--- /dev/null
+++ b/src/declarative/qml/qmlengine_p.h
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLENGINE_P_H
+#define QMLENGINE_P_H
+
+#include <QtScript/QScriptClass>
+#include <QtScript/QScriptValue>
+#include <QtScript/QScriptString>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstack.h>
+#include <private/qobject_p.h>
+#include <private/qmlclassfactory_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <QtDeclarative/qml.h>
+#include <private/qmlbasicscript_p.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtScript/qscriptengine.h>
+
+QT_BEGIN_NAMESPACE
+class QmlContext;
+class QmlEngine;
+class QmlContextPrivate;
+class QmlExpression;
+class QmlBasicScriptNodeCache;
+class QmlContextScriptClass;
+class QmlObjectScriptClass;
+class QScriptEngineDebugger;
+class QNetworkReply;
+class QNetworkAccessManager;
+
+class QmlEnginePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEngine)
+public:
+ QmlEnginePrivate(QmlEngine *);
+ ~QmlEnginePrivate();
+
+ void init();
+
+ void contextActivated(QmlContext *);
+ void contextDeactivated(QmlContext *);
+
+ bool fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *);
+ bool loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context);
+
+ QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *);
+ QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0);
+
+ struct CapturedProperty {
+ CapturedProperty(QObject *, int);
+ CapturedProperty(const QmlMetaProperty &);
+ CapturedProperty(const CapturedProperty &);
+ CapturedProperty &operator=(const CapturedProperty &);
+
+ QObject *object;
+ QString name;
+ int notifyIndex;
+ };
+ QList<CapturedProperty> capturedProperties;
+
+ QmlContext *rootContext;
+ QmlContext *currentBindContext;
+ QmlExpression *currentExpression;
+ QmlEngine *q;
+#ifdef QT_SCRIPTTOOLS_LIB
+ QScriptEngineDebugger *debugger;
+#endif
+
+ QmlContextScriptClass *contextClass;
+ QmlObjectScriptClass *objectClass;
+
+ QmlContext *setCurrentBindContext(QmlContext *);
+ QStack<QmlContext *> activeContexts;
+
+ QScriptEngine scriptEngine;
+
+ template<class T>
+ struct SimpleList {
+ SimpleList()
+ : count(0), values(0) {}
+ SimpleList(int r)
+ : count(0), values(new T*[r]) {}
+
+ int count;
+ T **values;
+
+ void append(T *v) {
+ values[count++] = v;
+ }
+
+ T *at(int idx) const {
+ return values[idx];
+ }
+
+ void clear() {
+ delete [] values;
+ }
+ };
+
+ static void clear(SimpleList<QmlBindableValue> &);
+ static void clear(SimpleList<QmlParserStatus> &);
+
+ QList<SimpleList<QmlBindableValue> > bindValues;
+ QList<SimpleList<QmlParserStatus> > parserStatus;
+
+ QmlComponent *rootComponent;
+ mutable QNetworkAccessManager *networkAccessManager;
+
+ QmlCompositeTypeManager typeManager;
+ QMap<QString,QString> nameSpacePaths;
+
+ mutable quint32 uniqueId;
+ quint32 getUniqueId() const {
+ return uniqueId++;
+ }
+};
+
+
+class BindExpressionProxy : public QObject
+{
+Q_OBJECT
+public:
+ BindExpressionProxy(QmlExpression *be)
+ :e(be)
+ {
+ }
+
+private:
+ QmlExpression *e;
+
+private Q_SLOTS:
+ void changed();
+};
+
+class QmlScriptClass : public QScriptClass
+{
+public:
+ enum ClassId
+ {
+ InvalidId = -1,
+
+ FunctionId = 0x80000000,
+ VariantPropertyId = 0x40000000,
+ PropertyId = 0x00000000,
+
+ ClassIdMask = 0xC0000000,
+
+ ClassIdSelectorMask = 0x3F000000,
+ };
+
+ QmlScriptClass(QmlEngine *);
+
+protected:
+ QmlEngine *engine;
+};
+
+class QmlContextScriptClass : public QmlScriptClass
+{
+public:
+ QmlContextScriptClass(QmlEngine *);
+ ~QmlContextScriptClass();
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id);
+ virtual void setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value);
+};
+
+class QmlObjectScriptClass : public QmlScriptClass
+{
+public:
+ QmlObjectScriptClass(QmlEngine *);
+ ~QmlObjectScriptClass();
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id);
+ virtual void setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value);
+};
+
+class QmlExpressionLog
+{
+public:
+ QmlExpressionLog();
+ QmlExpressionLog(const QmlExpressionLog &);
+ ~QmlExpressionLog();
+
+ QmlExpressionLog &operator=(const QmlExpressionLog &);
+
+ void setTime(quint32);
+ quint32 time() const;
+
+ QString expression() const;
+ void setExpression(const QString &);
+
+ QStringList warnings() const;
+ void addWarning(const QString &);
+
+ QVariant result() const;
+ void setResult(const QVariant &);
+
+private:
+ quint32 m_time;
+ QString m_expression;
+ QVariant m_result;
+ QStringList m_warnings;
+};
+
+class QmlExpressionPrivate
+{
+public:
+ QmlExpressionPrivate(QmlExpression *);
+ QmlExpressionPrivate(QmlExpression *, const QString &expr);
+ QmlExpressionPrivate(QmlExpression *, void *expr, QmlRefCount *rc);
+ ~QmlExpressionPrivate();
+
+ QmlExpression *q;
+ QmlContext *ctxt;
+ QString expression;
+ QmlBasicScript sse;
+ void *sseData;
+ BindExpressionProxy *proxy;
+ QObject *me;
+ bool trackChange;
+ QString fileName;
+ int line;
+
+ quint32 id;
+
+ void addLog(const QmlExpressionLog &);
+ QList<QmlExpressionLog> *log;
+};
+QT_END_NAMESPACE
+
+#endif // QMLENGINE_P_H
+
diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp
new file mode 100644
index 0000000..149e173
--- /dev/null
+++ b/src/declarative/qml/qmlerror.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlerror.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlError
+ \brief The QmlError class encapsulates a QML error
+*/
+class QmlErrorPrivate
+{
+public:
+ QmlErrorPrivate();
+
+ QUrl url;
+ QString description;
+ int line;
+ int column;
+};
+
+QmlErrorPrivate::QmlErrorPrivate()
+: line(-1), column(-1)
+{
+}
+
+/*!
+ Create an empty error object.
+*/
+QmlError::QmlError()
+: d(new QmlErrorPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlError::QmlError(const QmlError &other)
+: d(new QmlErrorPrivate)
+{
+ *this = other;
+}
+
+/*!
+ Assign \a other to this error object.
+*/
+QmlError &QmlError::operator=(const QmlError &other)
+{
+ d->url = other.d->url;
+ d->description = other.d->description;
+ d->line = other.d->line;
+ d->column = other.d->column;
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QmlError::~QmlError()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Return the url for the file that caused this error.
+*/
+QUrl QmlError::url() const
+{
+ return d->url;
+}
+
+/*!
+ Set the \a url for the file that caused this error.
+*/
+void QmlError::setUrl(const QUrl &url)
+{
+ d->url = url;
+}
+
+/*!
+ Return the error description.
+*/
+QString QmlError::description() const
+{
+ return d->description;
+}
+
+/*!
+ Set the error \a description.
+*/
+void QmlError::setDescription(const QString &description)
+{
+ d->description = description;
+}
+
+/*!
+ Return the error line number.
+*/
+int QmlError::line() const
+{
+ return d->line;
+}
+
+/*!
+ Set the error \a line number.
+*/
+void QmlError::setLine(int line)
+{
+ d->line = line;
+}
+
+/*!
+ Return the error column number.
+*/
+int QmlError::column() const
+{
+ return d->column;
+}
+
+/*!
+ Set the error \a column number.
+*/
+void QmlError::setColumn(int column)
+{
+ d->column = column;
+}
+
+/*!
+ \relates QmlError
+ \fn QDebug operator<<(QDebug debug, const QmlError &error)
+
+ Output a human readable version of \a error to \a debug.
+*/
+
+QDebug operator<<(QDebug debug, const QmlError &error)
+{
+ QUrl url = error.url();
+
+ QString output;
+
+ output = url.toString() + QLatin1String(":") +
+ QString::number(error.line());
+
+ if(error.column() != -1)
+ output += QLatin1String(":") + QString::number(error.column());
+
+ output += QLatin1String(": ") + error.description();
+
+ debug << qPrintable(output);
+
+ if (error.line() > 0 && url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ debug << "\n " << qPrintable(line);
+
+ if(error.column() > 0) {
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ debug << "\n " << ind.constData();
+ }
+ }
+ }
+ }
+ return debug;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlerror.h b/src/declarative/qml/qmlerror.h
new file mode 100644
index 0000000..57d2f8f
--- /dev/null
+++ b/src/declarative/qml/qmlerror.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLERROR_H
+#define QMLERROR_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDebug;
+class QmlErrorPrivate;
+class Q_DECLARATIVE_EXPORT QmlError
+{
+public:
+ QmlError();
+ QmlError(const QmlError &);
+ QmlError &operator=(const QmlError &);
+ ~QmlError();
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ QString description() const;
+ void setDescription(const QString &);
+ int line() const;
+ void setLine(int);
+ int column() const;
+ void setColumn(int);
+private:
+ QmlErrorPrivate *d;
+};
+
+QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, const QmlError &error);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLERROR_H
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
new file mode 100644
index 0000000..651fd9c
--- /dev/null
+++ b/src/declarative/qml/qmlexpression.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLEXPRESSION_H
+#define QMLEXPRESSION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlRefCount;
+class QmlEngine;
+class QmlContext;
+class QmlExpressionPrivate;
+class QmlBasicScript;
+class Q_DECLARATIVE_EXPORT QmlExpression
+{
+public:
+ QmlExpression();
+ QmlExpression(QmlContext *, const QString &, QObject *);
+ QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me);
+ virtual ~QmlExpression();
+
+ QmlEngine *engine() const;
+ QmlContext *context() const;
+
+ QString expression() const;
+ void clearExpression();
+ virtual void setExpression(const QString &);
+ QVariant value();
+ bool isConstant() const;
+
+ bool trackChange() const;
+ void setTrackChange(bool);
+
+ void setSourceLocation(const QString &fileName, int line);
+
+ QObject *scopeObject() const;
+
+ quint32 id() const;
+protected:
+ virtual void valueChanged();
+
+private:
+ friend class BindExpressionProxy;
+ friend class QmlDebugger;
+ friend class QmlContext;
+ QmlExpressionPrivate *d;
+};
+
+// LK: can't we merge with QmlExpression????
+class Q_DECLARATIVE_EXPORT QmlExpressionObject : public QObject,
+ public QmlExpression
+{
+ Q_OBJECT
+public:
+ QmlExpressionObject(QObject *parent = 0);
+ QmlExpressionObject(QmlContext *, const QString &, QObject *scope, QObject *parent = 0);
+ QmlExpressionObject(QmlContext *, void *, QmlRefCount *, QObject *);
+
+public Q_SLOTS:
+ QVariant value();
+
+Q_SIGNALS:
+ void valueChanged();
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLEXPRESSION_H
+
diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp
new file mode 100644
index 0000000..65a4298
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlinfo.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlInfo
+ \brief The QmlInfo class prints warnings messages that include the file and line number for QML types.
+
+ When QML types display warning messages, it improves tracibility
+ if they include the QML file and line number on which the
+ particular instance was instantiated.
+
+ QmlInfo statements work just like regular Qt qDebug() statements.
+ To include the file and line number, an object must be passed. If
+ the file and line number is not available for that instance
+ (either it was not instantiated by the QML engine or location
+ information is disabled), "unknown location" will be used instead.
+
+ For example,
+
+ \code
+ qmlInfo(this) << "component property is a write-once property";
+ \endcode
+
+ prints
+
+ \code
+ QML ComponentInstance (unknown location): component property is a write-once property
+ \endcode
+*/
+
+/*!
+ Construct a QmlInfo, using \a object for file and line number
+ information.
+*/
+QmlInfo::QmlInfo(QObject *object)
+: QDebug(QtWarningMsg)
+{
+ *this << "QML";
+ if (object)
+ *this << object->metaObject()->className();
+ *this << "(unknown location):";
+}
+
+/*!
+ The destructor does nothing special.
+*/
+QmlInfo::~QmlInfo()
+{
+}
+
+/*!
+ \relates QmlInfo
+ \fn QmlInfo qmlInfo(QObject *me)
+ Constructs an instance of QmlInfo from \a me and returns it.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinfo.h b/src/declarative/qml/qmlinfo.h
new file mode 100644
index 0000000..da8144c
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINFO_H
+#define QMLINFO_H
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlInfo : public QDebug
+{
+public:
+ QmlInfo(QObject *);
+ ~QmlInfo();
+};
+
+Q_DECLARATIVE_EXPORT inline QmlInfo qmlInfo(QObject *me)
+{
+ return QmlInfo(me);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLINFO_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
new file mode 100644
index 0000000..0aa860d
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qmlinstruction_p.h"
+#include "private/qmlcompiledcomponent_p.h"
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
+{
+ QByteArray lineNumber = QByteArray::number(instr->line);
+ if (instr->line == (unsigned short)-1)
+ lineNumber = "NA";
+ const char *line = lineNumber.constData();
+
+ switch(instr->type) {
+ case QmlInstruction::Init:
+ qWarning() << idx << "\t" << line << "\t" << "INIT\t\t\t" << instr->init.dataSize;
+ break;
+ case QmlInstruction::CreateObject:
+ qWarning() << idx << "\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
+ break;
+ case QmlInstruction::SetId:
+ qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t" << instr->setId.save << "\t\t" << primitives.at(instr->setId.value);
+ break;
+ case QmlInstruction::SetDefault:
+ qWarning() << idx << "\t" << line << "\t" << "SET_DEFAULT";
+ break;
+ case QmlInstruction::CreateComponent:
+ qWarning() << idx << "\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
+ break;
+ case QmlInstruction::StoreMetaObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t" << instr->storeMeta.slotData;
+ break;
+ case QmlInstruction::StoreReal:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_REAL\t\t" << instr->storeReal.propertyIndex << "\t" << instr->storeReal.value;
+ break;
+ case QmlInstruction::StoreInteger:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
+ break;
+ case QmlInstruction::StoreBool:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
+ break;
+ case QmlInstruction::StoreString:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreColor:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t" << QString::number(instr->storeColor.value, 16);
+ break;
+ case QmlInstruction::StoreDate:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value;
+ break;
+ case QmlInstruction::StoreTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex;
+ break;
+ case QmlInstruction::StoreDateTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex;
+ break;
+ case QmlInstruction::StorePoint:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StorePointF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSize:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSizeF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreRect:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreRectF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreVariant:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex;
+ break;
+ case QmlInstruction::AssignCustomType:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
+ break;
+ case QmlInstruction::StoreSignal:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value);
+ break;
+ case QmlInstruction::AssignSignalObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal);
+ break;
+ case QmlInstruction::StoreBinding:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << primitives.at(instr->assignBinding.value);
+ break;
+ case QmlInstruction::StoreCompiledBinding:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context;
+ break;
+ case QmlInstruction::StoreValueSource:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property;
+ break;
+ case QmlInstruction::BeginObject:
+ qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue;
+ break;
+ case QmlInstruction::CompleteObject:
+ qWarning() << idx << "\t" << line << "\t" << "COMPLETE\t\t" << instr->complete.castValue;
+ break;
+ case QmlInstruction::AssignObjectList:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t" << instr->assignObject.property << "\t" << instr->assignObject.castValue << "\t\t" << ((instr->assignObject.property == -1)?QByteArray("default"):datas.at(instr->assignObject.property));
+ break;
+ case QmlInstruction::FetchAttached:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id;
+ break;
+ case QmlInstruction::FetchQmlList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QMLLIST\t\t" << instr->fetchQmlList.property << "\t" << instr->fetchQmlList.type;
+ break;
+ case QmlInstruction::FetchQList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QLIST\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::FetchObject:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH\t\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::PopFetchedObject:
+ qWarning() << idx << "\t" << line << "\t" << "POP";
+ break;
+ case QmlInstruction::PopQList:
+ qWarning() << idx << "\t" << line << "\t" << "POP_QLIST";
+ break;
+ case QmlInstruction::PushProperty:
+ qWarning() << idx << "\t" << line << "\t" << "PUSH_PROPERTY" << "\t\t" << instr->pushProperty.property;
+ break;
+ case QmlInstruction::StoreStackObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_STACK_OBJ" << "\t" << instr->assignStackObject.property << "\t" << instr->assignStackObject.object;
+ break;
+ default:
+ qWarning() << idx << "\t" << line << "\t" << "XXX UNKOWN INSTRUCTION";
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
new file mode 100644
index 0000000..5c6fa5a
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINSTRUCTION_P_H
+#define QMLINSTRUCTION_P_H
+
+#include <QtDeclarative/qfxglobal.h>
+
+
+QT_BEGIN_NAMESPACE
+class QmlCompiledComponent;
+class Q_DECLARATIVE_EXPORT QmlInstruction
+{
+public:
+ enum Type {
+ //
+ // Object Creation
+ //
+ // CreateObject - Create a new object instance and push it on the
+ // object stack
+ // SetId - Set the id of the object on the top of the object stack
+ // SetDefault - Sets the instance on the top of the object stack to
+ // be the context's default object.
+ // StoreMetaObject - Assign the dynamic metaobject to object on the
+ // top of the stack.
+ Init, /* init */
+ CreateObject, /* create */
+ SetId, /* setId */
+ SetDefault,
+ CreateComponent, /* createComponent */
+ StoreMetaObject, /* storeMeta */
+
+ //
+ // Precomputed single assignment
+ //
+ // StoreReal - Store a qreal in a core property
+ // StoreInteger - Store a int or uint in a core property
+ // StoreBool - Store a bool in a core property
+ // StoreString - Store a QString in a core property
+ // StoreColor - Store a QColor in a core property
+ // StoreDate - Store a QDate in a core property
+ // StoreTime - Store a QTime in a core property
+ // StoreDateTime - Store a QDateTime in a core property
+ // StoreVariant - Store a QVariant in a core property
+ // StoreObject - Pop the object on the top of the object stack and
+ // store it in a core property
+ StoreReal, /* storeReal */
+ StoreInteger, /* storeInteger */
+ StoreBool, /* storeBool */
+ StoreString, /* storeString */
+ StoreColor, /* storeColor */
+ StoreDate, /* storeDate */
+ StoreTime, /* storeTime */
+ StoreDateTime, /* storeDateTime */
+ StorePoint, /* storeRealPair */
+ StorePointF, /* storeRealPair */
+ StoreSize, /* storeRealPair */
+ StoreSizeF, /* storeRealPair */
+ StoreRect, /* storeRect */
+ StoreRectF, /* storeRect */
+ StoreVariant, /* storeString */
+ StoreObject, /* storeObject */
+ StoreVariantObject, /* storeObject */
+ StoreInterface, /* storeObject */
+
+ StoreSignal, /* storeSignal */
+
+ StoreObjectQmlList,
+
+ // XXX need to handle storing objects in variants
+
+ //
+ // Unresolved single assignment
+ //
+ AssignSignalObject, /* assignSignalObject */
+ AssignCustomType, /* assignCustomType */
+
+ StoreBinding, /* assignBinding */
+ StoreCompiledBinding, /* assignBinding */
+ StoreValueSource, /* assignValueSource */
+
+ BeginObject, /* begin */
+ CompleteObject, /* complete */
+
+ AssignObjectList, /* assignObject */
+
+ FetchAttached, /* fetchAttached */
+ FetchQmlList, /* fetchQmlList */
+ FetchQList, /* fetch */
+ FetchObject, /* fetch */
+
+ //
+ // Stack manipulation
+ //
+ // PopFetchedObject - Remove an object from the object stack
+ // PopQList - Remove a list from the list stack
+ PopFetchedObject,
+ PopQList,
+
+ //
+ // Expression optimizations
+ //
+ // PushProperty - Save the property for later use
+ // StoreStackObject - Assign the stack object (no checks)
+ PushProperty, /* pushProperty */
+ StoreStackObject /* assignStackObject */
+ };
+ QmlInstruction()
+ : line(0) {}
+
+ Type type;
+ unsigned short line;
+ union {
+ struct {
+ int dataSize;
+ int bindingsSize;
+ int parserStatusSize;
+ } init;
+ struct {
+ int type;
+ int data;
+ } create;
+ struct {
+ int data;
+ int slotData;
+ } storeMeta;
+ struct {
+ int value;
+ int save;
+ } setId;
+ struct {
+ int property;
+ int castValue;
+ } assignObject;
+ struct {
+ int property;
+ } assignValueSource;
+ struct {
+ int property;
+ int value;
+ short context;
+ short category;
+ } assignBinding;
+ struct {
+ int property;
+ bool isObject;
+ } fetch;
+ struct {
+ int property;
+ int type;
+ } fetchQmlList;
+ struct {
+ int castValue;
+ } complete;
+ struct {
+ int castValue;
+ } begin;
+ struct {
+ int propertyIndex;
+ float value;
+ } storeReal;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeInteger;
+ struct {
+ int propertyIndex;
+ bool value;
+ } storeBool;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeString;
+ struct {
+ int propertyIndex;
+ unsigned int value;
+ } storeColor;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeDate;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeDateTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRealPair;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRect;
+ struct {
+ int propertyIndex;
+ } storeObject;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } assignCustomType;
+ struct {
+ int signalIndex;
+ int value;
+ } storeSignal;
+ struct {
+ int signal;
+ } assignSignalObject;
+ struct {
+ int count;
+ int endLine;
+ int metaObject;
+ } createComponent;
+ struct {
+ int id;
+ } fetchAttached;
+ struct {
+ int property;
+ } pushProperty;
+ struct {
+ int property;
+ int object;
+ } assignStackObject;
+ };
+
+ void dump(QmlCompiledComponent *);
+};
+
+#endif // QMLINSTRUCTION_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmllist.h b/src/declarative/qml/qmllist.h
new file mode 100644
index 0000000..cc13924
--- /dev/null
+++ b/src/declarative/qml/qmllist.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLIST_H
+#define QMLLIST_H
+
+#include <QtDeclarative/qmlprivate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<typename T>
+class QmlList : private QmlPrivate::ListInterface
+{
+public:
+ virtual void append(T) = 0;
+ virtual void insert(int, T) = 0;
+ virtual void removeAt(int) = 0;
+ virtual T at(int) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ QmlList<T> &operator<<(T t) { append(t); return *this; }
+
+protected:
+ virtual int type() const { return qMetaTypeId<T>(); }
+ virtual void append(void *d) { const T &v = *(T *)d; append(v); }
+ virtual void insert(int i, void *d) { const T &v = *(T *)d; insert(i, v); }
+ virtual void at(int i, void *p) const { const T &v = at(i); *((T*)p) = v; }
+};
+
+template<typename T>
+class QmlConcreteList : public QList<T>, public QmlList<T>
+{
+public:
+ virtual void append(T v) { QList<T>::append(v); }
+ virtual void insert(int i, T v) { QList<T>::insert(i, v); }
+ virtual void clear() { QList<T>::clear(); }
+ virtual T at(int i) const { return QList<T>::at(i); }
+ virtual void removeAt(int i) { QList<T>::removeAt(i); }
+ virtual int count() const { return QList<T>::count(); }
+};
+
+#define QML_DECLARE_LIST_PROXY(ClassName, ListType, ListName) \
+class Qml_ProxyList_ ##ListName : public QmlList<ListType> \
+{ \
+ public: \
+ virtual void removeAt(int idx) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _removeAt(idx); \
+ } \
+ virtual int count() const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _count(); \
+ } \
+ virtual void append(ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _append(v); \
+ } \
+ virtual void insert(int idx, ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _insert(idx, v); \
+ } \
+ virtual ListType at(int idx) const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _at(idx); \
+ } \
+ virtual void clear() \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _clear(); \
+ } \
+}; \
+friend class Qml_ProxyList_ ##ListName ; \
+Qml_ProxyList_##ListName ListName;
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLIST_H
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
new file mode 100644
index 0000000..4f39ebc
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -0,0 +1,1123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlmetaproperty.h"
+#include "qmlmetaproperty_p.h"
+#include <qml.h>
+#include <qfxperf.h>
+#include <QStringList>
+#include <qmlbindablevalue.h>
+#include <qmlcontext.h>
+#include "qmlboundsignal_p.h"
+#include <math.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMetaPropertyEx : public QMetaProperty
+{
+public:
+ QMetaPropertyEx()
+ : propertyType(-1) {}
+
+ QMetaPropertyEx(const QMetaProperty &p)
+ : QMetaProperty(p), propertyType(p.userType()) {}
+
+ QMetaPropertyEx(const QMetaPropertyEx &o)
+ : QMetaProperty(o),
+ propertyType(o.propertyType) {}
+
+ QMetaPropertyEx &operator=(const QMetaPropertyEx &o)
+ {
+ static_cast<QMetaProperty *>(this)->operator=(o);
+ propertyType = o.propertyType;
+ return *this;
+ }
+
+ private:
+ friend class QmlMetaProperty;
+ int propertyType;
+};
+
+
+/*!
+ \class QmlMetaProperty
+ \brief The QmlMetaProperty class abstracts accessing QML properties.
+ */
+
+/*!
+ Create an invalid QmlMetaProperty.
+*/
+QmlMetaProperty::QmlMetaProperty()
+: d(new QmlMetaPropertyPrivate)
+{
+}
+
+/*!
+ The destructor deletes its heap data.
+ */
+QmlMetaProperty::~QmlMetaProperty()
+{
+ delete d; d = 0;
+}
+
+struct CachedPropertyData {
+ CachedPropertyData(const QString &n, int pt, int ci)
+ : name(n), propType(pt), coreIdx(ci) {}
+ QString name;
+ int propType;
+ int coreIdx;
+};
+
+// ### not thread safe
+static QHash<const QMetaObject *, CachedPropertyData> qmlCacheDefProp;
+
+/*!
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj)
+{
+ initDefault(obj);
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ initDefault(obj);
+}
+
+void QmlMetaProperty::initDefault(QObject *obj)
+{
+ if (!obj)
+ return;
+
+ d->object = obj;
+ QHash<const QMetaObject *, CachedPropertyData>::ConstIterator iter =
+ qmlCacheDefProp.find(obj->metaObject());
+ if (iter != qmlCacheDefProp.end()) {
+ d->name = iter->name;
+ d->propType = iter->propType;
+ d->coreIdx = iter->coreIdx;
+ } else {
+ QMetaPropertyEx p(QmlMetaType::defaultProperty(obj));
+ d->name = QLatin1String(p.name());
+ d->propType = p.propertyType;
+ d->coreIdx = p.propertyIndex();
+ if (!QObjectPrivate::get(obj)->metaObject)
+ qmlCacheDefProp.insert(obj->metaObject(), CachedPropertyData(d->name, d->propType, d->coreIdx));
+ }
+ if (!d->name.isEmpty()) {
+ d->type = Property | Default;
+ }
+}
+
+/*!
+ \internal
+
+ Creates a QmlMetaProperty for the property at index \a idx of \a obj.
+
+ The QmlMetaProperty is assigned category \a cat.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, PropertyCategory cat, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ d->object = obj;
+ d->type = Property;
+ d->category = cat;
+ QMetaPropertyEx p(obj->metaObject()->property(idx));
+ d->propType = p.propertyType;
+ d->coreIdx = idx;
+ if (p.name() != 0)
+ d->name = QLatin1String(p.name());
+}
+
+// ### Not thread safe!!!!
+static QHash<const QMetaObject *, QHash<QString, CachedPropertyData> > qmlCacheProps;
+/*!
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name)
+: d(new QmlMetaPropertyPrivate)
+{
+ initProperty(obj, name);
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ initProperty(obj, name);
+}
+
+void QmlMetaProperty::initProperty(QObject *obj, const QString &name)
+{
+ d->name = name;
+ d->object = obj;
+ if (name.isEmpty() || !obj)
+ return;
+
+ if (name.at(0).isUpper()) {
+ // Attached property
+ d->attachedFunc = QmlMetaType::attachedPropertiesFuncId(name.toLatin1());
+ if (d->attachedFunc != -1)
+ d->type = Property | Attached;
+ return;
+ } else if (name.count() >= 3 && name.startsWith(QLatin1String("on")) && name.at(2).isUpper()) {
+ // Signal
+ QString signalName = name.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ d->findSignalInt(obj, signalName);
+ if (d->signal.signature() != 0) {
+ d->type = SignalProperty;
+ return;
+ }
+ }
+
+ // Property
+ QHash<QString, CachedPropertyData> &props = qmlCacheProps[obj->metaObject()];
+ QHash<QString, CachedPropertyData>::ConstIterator iter = props.find(name);
+ if (iter != props.end()) {
+ d->name = iter->name;
+ d->propType = iter->propType;
+ d->coreIdx = iter->coreIdx;
+ } else {
+ QMetaPropertyEx p = QmlMetaType::property(obj, name.toLatin1().constData());
+ d->name = QLatin1String(p.name());
+ d->propType = p.propertyType;
+ d->coreIdx = p.propertyIndex();
+ if (!QObjectPrivate::get(obj)->metaObject)
+ props.insert(name, CachedPropertyData(d->name, d->propType, d->coreIdx));
+ }
+ if (!d->name.isEmpty())
+ d->type = Property;
+
+ if (d->type == Invalid) {
+ int sig = findSignal(obj, name.toLatin1());
+ if (sig != -1) {
+ d->signal = obj->metaObject()->method(sig);
+ d->type = Signal;
+ d->coreIdx = sig;
+ }
+ }
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other)
+: d(new QmlMetaPropertyPrivate(*other.d))
+{
+}
+
+/*!
+ \enum QmlMetaProperty::PropertyCategory
+
+ This enum specifies a category of QML property.
+
+ \value Unknown The category is unknown. This will never be returned from propertyCategory()
+ \value InvalidProperty The property is invalid.
+ \value Bindable The property is a QmlBindableValue.
+ \value List The property is a QList pointer
+ \value QmlList The property is a QmlList pointer
+ \value Object The property is a QObject derived type pointer
+ \value Normal The property is none of the above.
+ */
+
+/*!
+ \enum QmlMetaProperty::Type
+
+ This enum specifies a type of QML property.
+
+ \value Invalid The property is invalid.
+ \value Property The property is a regular Qt property.
+ \value SignalProperty The property is a signal property.
+ \value Signal The property is a signal.
+ \value Default The property is the default property.
+ \value Attached The property is an attached property.
+*/
+
+/*!
+ Returns the property category.
+*/
+QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
+{
+ return d->propertyCategory();
+}
+
+QmlMetaProperty::PropertyCategory
+QmlMetaPropertyPrivate::propertyCategory() const
+{
+ if (category == QmlMetaProperty::Unknown) {
+ int type = propertyType();
+ if (type == QmlMetaProperty::Invalid)
+ category = QmlMetaProperty::InvalidProperty;
+ else if (type == qMetaTypeId<QmlBindableValue *>())
+ category = QmlMetaProperty::Bindable;
+ else if (QmlMetaType::isList(type))
+ category = QmlMetaProperty::List;
+ else if (QmlMetaType::isQmlList(type))
+ category = QmlMetaProperty::QmlList;
+ else if (QmlMetaType::isObject(type))
+ category = QmlMetaProperty::Object;
+ else
+ category = QmlMetaProperty::Normal;
+ }
+ return category;
+}
+
+/*!
+ Returns the property category of \a prop.
+*/
+QmlMetaProperty::PropertyCategory
+QmlMetaProperty::propertyCategory(const QMetaProperty &prop)
+{
+ if (prop.name()) {
+ int type = 0;
+ if (prop.type() == QVariant::LastType)
+ type = qMetaTypeId<QVariant>();
+ else if (prop.type() == QVariant::UserType)
+ type = prop.userType();
+ else
+ type = prop.type();
+
+ if (type == qMetaTypeId<QmlBindableValue *>())
+ return Bindable;
+ else if (QmlMetaType::isList(type))
+ return List;
+ else if (QmlMetaType::isQmlList(type))
+ return QmlList;
+ else if (QmlMetaType::isObject(type))
+ return Object;
+ else
+ return Normal;
+ } else {
+ return InvalidProperty;
+ }
+}
+
+/*!
+ Returns the type name of the property, or 0 if the property has no type
+ name.
+*/
+const char *QmlMetaProperty::propertyTypeName() const
+{
+ if (!d->name.isEmpty()) {
+ return d->object->metaObject()->property(d->coreIdx).typeName();
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Returns true if \a other and this QmlMetaProperty represent the same
+ property.
+*/
+bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
+{
+ return d->name == other.d->name &&
+ d->signal.signature() == other.d->signal.signature() &&
+ d->type == other.d->type &&
+ d->object == other.d->object;
+}
+
+/*!
+ Returns the QVariant type of the property, or QVariant::Invalid if the
+ property has no QVariant type.
+*/
+int QmlMetaProperty::propertyType() const
+{
+ return d->propertyType();
+}
+
+int QmlMetaPropertyPrivate::propertyType() const
+{
+ int rv = QVariant::Invalid;
+
+ if (!name.isEmpty()) {
+ if (propType == (int)QVariant::LastType)
+ rv = qMetaTypeId<QVariant>();
+ else
+ rv = propType;
+ } else if (attachedFunc) {
+ rv = qMetaTypeId<QObject *>();
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the type of the property.
+*/
+QmlMetaProperty::Type QmlMetaProperty::type() const
+{
+ return (Type)d->type;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a regular Qt property.
+*/
+bool QmlMetaProperty::isProperty() const
+{
+ return type() & Property;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a default property.
+*/
+bool QmlMetaProperty::isDefault() const
+{
+ return type() & Default;
+}
+
+/*!
+ Returns the QmlMetaProperty's QObject.
+*/
+QObject *QmlMetaProperty::object() const
+{
+ return d->object;
+}
+
+/*!
+ Assign \a other to this QmlMetaProperty.
+*/
+QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
+{
+ d->name = other.d->name;
+ d->propType = other.d->propType;
+ d->type = other.d->type;
+ d->signal = other.d->signal;
+ d->coreIdx = other.d->coreIdx;
+ d->attachedFunc = other.d->attachedFunc;
+ d->object = other.d->object;
+ d->category = other.d->category;
+ return *this;
+}
+
+/*!
+ Returns true if the property is writable, otherwise false.
+*/
+bool QmlMetaProperty::isWritable() const
+{
+ if (propertyCategory() == List || propertyCategory() == QmlList)
+ return true;
+ else if (!d->name.isEmpty())
+ return d->object->metaObject()->property(d->coreIdx).isWritable();
+ else if (type() & SignalProperty)
+ return true;
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is designable, otherwise false.
+*/
+bool QmlMetaProperty::isDesignable() const
+{
+ if (!d->name.isEmpty())
+ return d->object->metaObject()->property(d->coreIdx).isDesignable();
+ else
+ return false;
+}
+
+/*!
+ Returns true if the QmlMetaProperty refers to a valid property, otherwise
+ false.
+*/
+bool QmlMetaProperty::isValid() const
+{
+ return type() != Invalid;
+}
+
+/*!
+ Returns all of \a obj's Qt properties.
+*/
+QStringList QmlMetaProperty::properties(QObject *obj)
+{
+ if (!obj)
+ return QStringList();
+
+ QStringList rv;
+ const QMetaObject *mo = obj->metaObject();
+ for (int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QMetaProperty prop = mo->property(ii);
+ rv << QLatin1String(prop.name());
+ }
+
+ return rv;
+}
+
+/*!
+ Return the name of this QML property.
+*/
+QString QmlMetaProperty::name() const
+{
+ return d->name;
+}
+
+/*!
+ Returns the \l{QMetaProperty} {Qt property} associated with
+ this QML property.
+ */
+QMetaProperty QmlMetaProperty::property() const
+{
+ return d->object->metaObject()->property(d->coreIdx);
+}
+
+/*!
+ Returns the binding associated with this property, or 0 if no binding
+ exists.
+*/
+QmlBindableValue *QmlMetaProperty::binding()
+{
+ if (!isProperty() || type() & Attached)
+ return 0;
+
+ const QObjectList &children = object()->children();
+ for (QObjectList::ConstIterator iter = children.begin();
+ iter != children.end(); ++iter) {
+ QObject *child = *iter;
+ if (child->metaObject() == &QmlBindableValue::staticMetaObject) {
+ QmlBindableValue *v = static_cast<QmlBindableValue *>(child);
+ if (v->property() == *this)
+ return v;
+ }
+ }
+ return 0;
+}
+
+/*! \internal */
+int QmlMetaProperty::findSignal(const QObject *obj, const char *name)
+{
+ const QMetaObject *mo = obj->metaObject();
+ int methods = mo->methodCount();
+ for (int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ if (method.methodType() != QMetaMethod::Signal)
+ continue;
+
+ QByteArray methodName = method.signature();
+ int idx = methodName.indexOf('(');
+ methodName = methodName.left(idx);
+
+ if (methodName == name)
+ return ii;
+ }
+ return -1;
+}
+
+void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
+{
+ const QMetaObject *mo = obj->metaObject();
+
+ int methods = mo->methodCount();
+ for (int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QLatin1String(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+
+ if (methodName == name) {
+ signal = method;
+ coreIdx = ii;
+ return;
+ }
+ }
+}
+
+QObject *QmlMetaPropertyPrivate::attachedObject() const
+{
+ if (attachedFunc == -1)
+ return 0;
+ else
+ return qmlAttachedPropertiesObjectById(attachedFunc, object);
+}
+
+/*!
+ Returns the property value.
+*/
+QVariant QmlMetaProperty::read() const
+{
+ if (type() & SignalProperty) {
+
+ const QObjectList &children = object()->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if (sig && sig->index() == d->coreIdx)
+ return sig->expression();
+ }
+ } else if (type() & Property) {
+ if (type() & Attached)
+ return QVariant::fromValue(d->attachedObject());
+ else
+ return d->object->metaObject()->property(d->coreIdx).read(object());
+ }
+ return QVariant();
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
+{
+ QString expr = value.toString();
+ const QObjectList &children = object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if (sig && sig->index() == coreIdx) {
+ if (expr.isEmpty()) {
+ sig->disconnect();
+ sig->deleteLater();
+ } else {
+ sig->setExpression(expr);
+ }
+ return;
+ }
+ }
+
+ if (!expr.isEmpty()) {
+ // XXX scope
+ (void *)new QmlBoundSignal(QmlContext::activeContext(), expr, object,
+ coreIdx, object);
+ }
+}
+
+void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value)
+{
+ QMetaProperty prop = object->metaObject()->property(coreIdx);
+ if (prop.isEnumType()) {
+ QVariant v = value;
+ if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ double integral;
+ double fractional = modf(value.toDouble(), &integral);
+ if (qFuzzyCompare(fractional, (double)0.0))
+ v.convert(QVariant::Int);
+ }
+ prop.write(object, v);
+ } else {
+ if (!value.isValid())
+ return;
+
+ int t = propertyType();
+ int vt = value.type();
+
+ if (vt == t ||
+ value.userType() == t) {
+
+ void *a[1];
+ a[0] = (void *)value.constData();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+
+ } else if (qMetaTypeId<QVariant>() == t) {
+
+ prop.write(object, value);
+
+ } else if (propertyCategory() == QmlMetaProperty::Object) {
+
+ QObject *o = QmlMetaType::toQObject(value);
+ if (o)
+ prop.write(object, QmlMetaType::fromObject(o, propertyType()));
+
+ } else if (propertyCategory() == QmlMetaProperty::List) {
+
+ int listType = QmlMetaType::listType(t);
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = prop.read(object);
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (vt == listType ||
+ value.userType() == listType) {
+ QVariant listVar = prop.read(object);
+ if (!QmlMetaType::append(listVar, value)) {
+ qWarning() << "QmlMetaProperty: Unable to assign object to list";
+ }
+ }
+ } else if (propertyCategory() == QmlMetaProperty::QmlList) {
+ // XXX - optimize!
+ QVariant list = prop.read(object);
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if (propertyCategory() == QmlMetaProperty::Normal) {
+
+ switch(t) {
+ case QVariant::Double:
+ {
+ double d;
+ bool found = true;
+ if (vt == QVariant::Int) {
+ d = value.toInt();
+ } else if (vt == QVariant::UInt) {
+ d = value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &d;
+ QMetaObject::metacall(object,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::Int:
+ {
+ int i;
+ bool found = true;
+ if (vt == QVariant::Double) {
+ i = (int)value.toDouble();
+ } else if (vt == QVariant::UInt) {
+ i = (int)value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &i;
+ QMetaObject::metacall(object,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::String:
+ {
+ QString s;
+ bool found = true;
+ if (vt == QVariant::ByteArray) {
+ s = QLatin1String(value.toByteArray());
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &s;
+ QMetaObject::metacall(object,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ prop.write(object, value);
+ }
+
+ }
+}
+
+/*!
+ Set the property value to \a value.
+*/
+void QmlMetaProperty::write(const QVariant &value) const
+{
+ QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ if (type() & SignalProperty) {
+
+ d->writeSignalProperty(value);
+
+ } else if (prop.name()) {
+
+ if (prop.isEnumType()) {
+ QVariant v = value;
+ if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ double integral;
+ double fractional = modf(value.toDouble(), &integral);
+ if (qFuzzyCompare(fractional, (double)0.0))
+ v.convert(QVariant::Int);
+ }
+ prop.write(object(), v);
+ } else {
+ if (!value.isValid())
+ return;
+
+ int t = propertyType();
+ int vt = value.type();
+
+ if (vt == t ||
+ value.userType() == t) {
+
+ void *a[1];
+ a[0] = (void *)value.constData();
+ QMetaObject::metacall(object(), QMetaObject::WriteProperty, d->coreIdx, a);
+
+ } else if (qMetaTypeId<QVariant>() == t) {
+
+ prop.write(object(), value);
+
+ } else if (propertyCategory() == Object) {
+
+ QObject *o = QmlMetaType::toQObject(value);
+ if (o)
+ prop.write(object(), QmlMetaType::fromObject(o, propertyType()));
+
+ } else if (propertyCategory() == List) {
+
+ int listType = QmlMetaType::listType(t);
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = prop.read(object());
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (vt == listType ||
+ value.userType() == listType) {
+ QVariant listVar = prop.read(object());
+ if (!QmlMetaType::append(listVar, value)) {
+ qWarning() << "QmlMetaProperty: Unable to assign object to list";
+ }
+ }
+ } else if (propertyCategory() == QmlList) {
+ // XXX - optimize!
+ QVariant list = prop.read(object());
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if (propertyCategory() == Normal) {
+
+ switch(t) {
+ case QVariant::Double:
+ {
+ double dd;
+ bool found = true;
+ if (vt == QVariant::Int) {
+ dd = value.toInt();
+ } else if (vt == QVariant::UInt) {
+ dd = value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &dd;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::Int:
+ {
+ int i;
+ bool found = true;
+ if (vt == QVariant::Double) {
+ i = (int)value.toDouble();
+ } else if (vt == QVariant::UInt) {
+ i = (int)value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &i;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::String:
+ {
+ QString s;
+ bool found = true;
+ if (vt == QVariant::ByteArray) {
+ s = QLatin1String(value.toByteArray());
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &s;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ prop.write(object(), value);
+ }
+
+ }
+ }
+}
+
+/*!
+ Returns true if the property has a change notifier signal, otherwise false.
+*/
+bool QmlMetaProperty::hasChangedNotifier() const
+{
+ if (type() & Property && !(type() & Attached)) {
+ return d->object->metaObject()->property(d->coreIdx).hasNotifySignal();
+ }
+ return false;
+}
+
+/*!
+ Returns true if the property needs a change notifier signal for bindings
+ to remain upto date, false otherwise.
+
+ Some properties, such as attached properties or those whose value never
+ changes, do not require a change notifier.
+*/
+bool QmlMetaProperty::needsChangedNotifier() const
+{
+ return type() & Property && !(type() & Attached);
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a method of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a method.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
+{
+ if (!(type() & Property) || type() & Attached)
+ return false;
+
+ QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ if (prop.hasNotifySignal()) {
+ return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a slot of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a slot.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
+{
+ if (!(type() & Property) || type() & Attached)
+ return false;
+
+ QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ if (prop.hasNotifySignal()) {
+ QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
+ return QObject::connect(d->object, signal.constData(), dest, slot);
+ } else {
+ return false;
+ }
+}
+
+/*! \internal */
+void QmlMetaProperty::emitSignal()
+{
+ if (type() & Signal) {
+ if (d->signal.parameterTypes().isEmpty())
+ d->object->metaObject()->activate(d->object, d->coreIdx, 0);
+ else
+ qWarning() << "QmlMetaProperty: Cannot emit signal with parameters";
+ }
+}
+
+/*!
+ Return the Qt metaobject index of the property.
+*/
+int QmlMetaProperty::coreIndex() const
+{
+ return d->coreIdx;
+}
+
+/*!
+ Returns the property information serialized into a single integer.
+ QmlMetaProperty uses the bottom 24 bits only.
+*/
+quint32 QmlMetaProperty::save() const
+{
+ quint32 rv = 0;
+ if (type() & Attached) {
+ rv = d->attachedFunc;
+ } else if (type() != Invalid) {
+ rv = d->coreIdx;
+ }
+
+ Q_ASSERT(rv <= 0xFFFF);
+ Q_ASSERT(type() <= 0xFF);
+ rv |= (type() << 16);
+
+ return rv;
+}
+
+/*!
+ Restore a QmlMetaProperty from a previously saved \a id.
+ \a obj must be the same object as used in the previous call
+ to QmlMetaProperty::save(). Only the bottom 24-bits are
+ used, the high bits can be set to any value.
+*/
+void QmlMetaProperty::restore(quint32 id, QObject *obj)
+{
+ *this = QmlMetaProperty();
+ d->object = obj;
+
+ id &= 0xFFFFFF;
+ d->type = id >> 16;
+ id &= 0xFFFF;
+
+ if (d->type & Attached) {
+ d->attachedFunc = id;
+ } else if (d->type & Property) {
+ QMetaPropertyEx p(obj->metaObject()->property(id));
+ d->name = QLatin1String(p.name());
+ d->propType = p.propertyType;
+ d->coreIdx = id;
+ } else if (d->type & SignalProperty || d->type & Signal) {
+ d->signal = obj->metaObject()->method(id);
+ d->coreIdx = id;
+ }
+}
+
+/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ return d->signal;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
new file mode 100644
index 0000000..9daef59
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETAPROPERTY_H
+#define QMLMETAPROPERTY_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtCore/QMetaProperty>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlBindableValue;
+class QStringList;
+class QVariant;
+struct QMetaObject;
+class QmlContext;
+
+class QmlMetaPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlMetaProperty
+{
+public:
+ enum PropertyCategory {
+ Unknown,
+ InvalidProperty,
+ Bindable,
+ List,
+ QmlList, //XXX
+ Object,
+ Normal
+ };
+ QmlMetaProperty();
+ QmlMetaProperty(QObject *);
+ QmlMetaProperty(QObject *, const QString &);
+ QmlMetaProperty(QObject *, QmlContext *);
+ QmlMetaProperty(QObject *, const QString &, QmlContext *);
+ QmlMetaProperty(const QmlMetaProperty &);
+ QmlMetaProperty &operator=(const QmlMetaProperty &);
+ QmlMetaProperty(QObject *, int, PropertyCategory = Unknown, QmlContext * = 0);
+ ~QmlMetaProperty();
+
+ static QStringList properties(QObject *);
+ QString name() const;
+
+ QVariant read() const;
+ void write(const QVariant &) const;
+ void emitSignal();
+
+ bool hasChangedNotifier() const;
+ bool needsChangedNotifier() const;
+ bool connectNotifier(QObject *dest, const char *slot) const;
+ bool connectNotifier(QObject *dest, int method) const;
+
+ quint32 save() const;
+ void restore(quint32, QObject *);
+
+ QMetaMethod method() const;
+
+ enum Type { Invalid = 0x00,
+ Property = 0x01,
+ SignalProperty = 0x02,
+ Signal = 0x04,
+ Default = 0x08,
+ Attached = 0x10 };
+
+ Type type() const;
+ bool isProperty() const;
+ bool isDefault() const;
+ bool isWritable() const;
+ bool isDesignable() const;
+ bool isValid() const;
+ QObject *object() const;
+
+ PropertyCategory propertyCategory() const;
+ static PropertyCategory propertyCategory(const QMetaProperty &);
+
+ int propertyType() const;
+ const char *propertyTypeName() const;
+
+ bool operator==(const QmlMetaProperty &) const;
+
+ QMetaProperty property() const;
+
+ QmlBindableValue *binding();
+ static int findSignal(const QObject *, const char *);
+
+ int coreIndex() const;
+private:
+ void initDefault(QObject *obj);
+ void initProperty(QObject *obj, const QString &name);
+ friend class QmlEnginePrivate;
+ QmlMetaPropertyPrivate *d;
+};
+typedef QList<QmlMetaProperty> QmlMetaProperties;
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETAPROPERTY_H
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
new file mode 100644
index 0000000..738bfec
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETAPROPERTY_P_H
+#define QMLMETAPROPERTY_P_H
+
+#include "qmlmetaproperty.h"
+
+class QmlContext;
+class QmlMetaPropertyPrivate
+{
+public:
+ QmlMetaPropertyPrivate()
+ : context(0), coreIdx(-1), type(QmlMetaProperty::Invalid), attachedFunc(-1),
+ object(0), propType(-1), category(QmlMetaProperty::Unknown) {}
+ QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
+ : name(other.name), signal(other.signal), context(other.context),
+ coreIdx(other.coreIdx), type(other.type), attachedFunc(other.attachedFunc),
+ object(other.object), propType(other.propType),
+ category(other.category) {}
+
+ QString name;
+ QMetaMethod signal;
+ QmlContext *context;
+ int coreIdx;
+ uint type;
+ int attachedFunc;
+ QObject *object;
+ int propType;
+
+ mutable QmlMetaProperty::PropertyCategory category;
+
+ QObject *attachedObject() const;
+ void findSignalInt(QObject *, const QString &);
+
+ int propertyType() const;
+ QmlMetaProperty::PropertyCategory propertyCategory() const;
+
+ void writeSignalProperty(const QVariant &);
+ void writeValueProperty(const QVariant &);
+};
+
+#endif // QMLMETAPROPERTY_P_H
+
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
new file mode 100644
index 0000000..3e25ae0
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -0,0 +1,1162 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlmetatype.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qbitarray.h>
+#include <QtCore/qreadwritelock.h>
+#include <private/qmlproxymetaobject_p.h>
+
+#include <qmetatype.h>
+#include <qobjectdefs.h>
+#include <qdatetime.h>
+#include <qbytearray.h>
+#include <qreadwritelock.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvector.h>
+#include <qlocale.h>
+#include <QtCore/qcryptographichash.h>
+#include <private/qmlcustomparser_p.h>
+
+QT_BEGIN_NAMESPACE
+#ifdef QT_BOOTSTRAPPED
+# ifndef QT_NO_GEOM_VARIANT
+# define QT_NO_GEOM_VARIANT
+# endif
+#else
+# include <qbitarray.h>
+# include <qurl.h>
+# include <qvariant.h>
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+# include <qsize.h>
+# include <qpoint.h>
+# include <qrect.h>
+# include <qline.h>
+#endif
+#define NS(x) QT_PREPEND_NAMESPACE(x)
+
+struct QmlMetaTypeData
+{
+ QList<QmlType *> types;
+ typedef QHash<int, QmlType *> Ids;
+ Ids idToType;
+ typedef QHash<QByteArray, QmlType *> Names;
+ Names nameToType;
+ typedef QHash<const QMetaObject *, QmlType *> MetaObjects;
+ MetaObjects metaObjectToType;
+ typedef QHash<int, QmlMetaType::StringConverter> StringConverters;
+ StringConverters stringConverters;
+
+ QBitArray objects;
+ QBitArray interfaces;
+ QBitArray qmllists;
+ QBitArray lists;
+};
+Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData)
+Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
+
+class QmlTypePrivate
+{
+public:
+ QmlTypePrivate();
+
+ void init() const;
+
+ bool m_isInterface : 1;
+ const char *m_iid;
+ QByteArray m_name;
+ int m_typeId; int m_listId; int m_qmlListId;
+ QmlPrivate::Func m_opFunc;
+ const QMetaObject *m_baseMetaObject;
+ QmlAttachedPropertiesFunc m_attachedPropertiesFunc;
+ const QMetaObject *m_attachedPropertiesType;
+ int m_parserStatusCast;
+ QmlPrivate::CreateFunc m_extFunc;
+ const QMetaObject *m_extMetaObject;
+ int m_index;
+ QmlCustomParser *m_customParser;
+ mutable volatile bool m_isSetup:1;
+ mutable QList<QmlProxyMetaObject::ProxyData> m_metaObjects;
+ mutable QByteArray m_hash;
+};
+
+QmlTypePrivate::QmlTypePrivate()
+: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0),
+ m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0),
+ m_parserStatusCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1),
+ m_customParser(0), m_isSetup(false)
+{
+}
+
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *iid, int index)
+: d(new QmlTypePrivate)
+{
+ d->m_isInterface = true;
+ d->m_iid = iid;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_index = index;
+ d->m_isSetup = true;
+}
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *qmlName,
+ const QMetaObject *metaObject,
+ QmlAttachedPropertiesFunc attachedPropertiesFunc,
+ const QMetaObject *attachedType,
+ int parserStatusCast, QmlPrivate::CreateFunc extFunc,
+ const QMetaObject *extMetaObject, int index,
+ QmlCustomParser *customParser)
+: d(new QmlTypePrivate)
+{
+ d->m_name = qmlName;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_baseMetaObject = metaObject;
+ d->m_attachedPropertiesFunc = attachedPropertiesFunc;
+ d->m_attachedPropertiesType = attachedType;
+ d->m_parserStatusCast = parserStatusCast;
+ d->m_extFunc = extFunc;
+ d->m_index = index;
+ d->m_customParser = customParser;
+
+ if (extMetaObject)
+ d->m_extMetaObject = extMetaObject;
+}
+
+QmlType::~QmlType()
+{
+ delete d;
+}
+
+void QmlTypePrivate::init() const
+{
+ if (m_isSetup) return;
+
+ QWriteLocker lock(metaTypeDataLock());
+ if (m_isSetup)
+ return;
+
+ // Setup extended meta object
+ // XXX - very inefficient
+ const QMetaObject *mo = m_baseMetaObject;
+ if (m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *m_extMetaObject;
+ mmo->d.superdata = mo;
+ QmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0 };
+ m_metaObjects << data;
+ }
+
+ mo = mo->d.superdata;
+ while(mo) {
+ QmlType *t = metaTypeData()->metaObjectToType.value(mo);
+ if (t) {
+ if (t->d->m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *t->d->m_extMetaObject;
+ mmo->d.superdata = m_baseMetaObject;
+ if (!m_metaObjects.isEmpty())
+ m_metaObjects.last().metaObject->d.superdata = mmo;
+ QmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0 };
+ m_metaObjects << data;
+ }
+ }
+ mo = mo->d.superdata;
+ }
+
+ for (int ii = 0; ii < m_metaObjects.count(); ++ii)
+ m_metaObjects[ii].propertyOffset =
+ m_metaObjects.at(ii).metaObject->propertyOffset();
+
+ // Calculate hash
+ QByteArray hashData;
+
+ const QMetaObject *myMetaObject = m_metaObjects.isEmpty()?m_baseMetaObject:m_metaObjects.first().metaObject;
+
+ for (int ii = 0; ii < myMetaObject->propertyCount(); ++ii) {
+ QMetaProperty prop = myMetaObject->property(ii);
+ hashData.append(prop.type());
+ hashData.append("|");
+ hashData.append(prop.name());
+ hashData.append("|");
+ }
+
+ for (int ii = 0; ii < myMetaObject->methodCount(); ++ii) {
+ QMetaMethod method = myMetaObject->method(ii);
+ hashData.append(method.signature());
+ hashData.append("|");
+ }
+
+ m_hash = QCryptographicHash::hash(hashData, QCryptographicHash::Md5);
+
+ m_isSetup = true;
+ lock.unlock();
+}
+
+QByteArray QmlType::typeName() const
+{
+ if (d->m_baseMetaObject)
+ return d->m_baseMetaObject->className();
+ else
+ return QByteArray();
+}
+
+QByteArray QmlType::qmlTypeName() const
+{
+ return d->m_name;
+}
+
+QByteArray QmlType::hash() const
+{
+ d->init();
+
+ return d->m_hash;
+}
+
+QObject *QmlType::create() const
+{
+ d->init();
+
+ QVariant v;
+ QObject *rv = 0;
+ d->m_opFunc(QmlPrivate::Create, 0, v, v, (void **)&rv);
+
+ if (rv && !d->m_metaObjects.isEmpty())
+ (void *)new QmlProxyMetaObject(rv, &d->m_metaObjects);
+
+ return rv;
+}
+
+QmlCustomParser *QmlType::customParser() const
+{
+ return d->m_customParser;
+}
+
+bool QmlType::isInterface() const
+{
+ return d->m_isInterface;
+}
+
+int QmlType::typeId() const
+{
+ return d->m_typeId;
+}
+
+int QmlType::qListTypeId() const
+{
+ return d->m_listId;
+}
+
+int QmlType::qmlListTypeId() const
+{
+ return d->m_qmlListId;
+}
+
+void QmlType::listClear(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant arg;
+ d->m_opFunc(QmlPrivate::Clear, 0, list, arg, 0);
+}
+
+void QmlType::listAppend(const QVariant &list, const QVariant &item)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ d->m_opFunc(QmlPrivate::Append, 0, list, item, 0);
+}
+
+QVariant QmlType::listAt(const QVariant &list, int idx)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant rv;
+ void *ptr = (void *)&rv;
+ d->m_opFunc(QmlPrivate::Value, idx, list, QVariant(), &ptr);
+ return rv;
+}
+
+int QmlType::listCount(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ return d->m_opFunc(QmlPrivate::Length, 0, list, QVariant(), 0);
+}
+
+const QMetaObject *QmlType::metaObject() const
+{
+ d->init();
+
+ if (d->m_metaObjects.isEmpty())
+ return d->m_baseMetaObject;
+ else
+ return d->m_metaObjects.first().metaObject;
+
+}
+
+const QMetaObject *QmlType::baseMetaObject() const
+{
+ return d->m_baseMetaObject;
+}
+
+QmlAttachedPropertiesFunc QmlType::attachedPropertiesFunction() const
+{
+ return d->m_attachedPropertiesFunc;
+}
+
+const QMetaObject *QmlType::attachedPropertiesType() const
+{
+ return d->m_attachedPropertiesType;
+}
+
+int QmlType::parserStatusCast() const
+{
+ return d->m_parserStatusCast;
+}
+
+QVariant QmlType::fromObject(QObject *obj) const
+{
+ QVariant rv;
+ QVariant *v_ptr = &rv;
+ QVariant vobj = QVariant::fromValue(obj);
+ d->m_opFunc(QmlPrivate::FromObject, 0, QVariant(), vobj, (void **)&v_ptr);
+ return rv;
+}
+
+const char *QmlType::interfaceIId() const
+{
+ return d->m_iid;
+}
+
+int QmlType::index() const
+{
+ return d->m_index;
+}
+
+int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id,
+ QmlPrivate::Func listFunction,
+ const char *iid)
+{
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ listFunction, iid, index);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+ if (!type->qmlTypeName().isEmpty())
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ if (data->interfaces.size() < id.typeId)
+ data->interfaces.resize(id.typeId + 16);
+ if (data->qmllists.size() < id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() < id.listId)
+ data->lists.resize(id.listId + 16);
+ data->interfaces.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser)
+{
+ Q_UNUSED(object);
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QString name = QLatin1String(cname);
+ for (int ii = 0; ii < name.count(); ++ii) {
+ if (!name.at(ii).isLetterOrNumber()) {
+ qWarning("QmlMetaType: Invalid QML name %s", cname);
+ return -1;
+ }
+ }
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ func, cname, mo, attach, attachMo, pStatus, extFunc,
+ extmo, index, parser);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+
+ if (!type->qmlTypeName().isEmpty())
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ data->metaObjectToType.insert(type->baseMetaObject(), type);
+
+ if (data->objects.size() <= id.typeId)
+ data->objects.resize(id.typeId + 16);
+ if (data->qmllists.size() <= id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() <= id.listId)
+ data->lists.resize(id.listId + 16);
+ data->objects.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::qmlParserStatusCast(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ if (type && type->typeId() == userType)
+ return type->parserStatusCast();
+ else
+ return -1;
+}
+
+QObject *QmlMetaType::toQObject(const QVariant &v)
+{
+ if (!isObject(v.userType()))
+ return 0;
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *rv = *(QObject **)v.constData();
+ return rv;
+}
+
+/*
+ Returns the item type for a list of type \a id.
+ */
+int QmlMetaType::listType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+/*
+ Returns the item type for a qml list of type \a id.
+ */
+int QmlMetaType::qmlListType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qmlListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::clear(const QVariant &list)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType) {
+ type->listClear(list);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QmlMetaType::append(const QVariant &list, const QVariant &item)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType &&
+ item.userType() == type->typeId()) {
+ type->listAppend(list, item);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+QObject *QmlMetaType::create(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ lock.unlock();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->create();
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::fromObject(QObject *obj, int typeId)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(typeId);
+ if (type && type->typeId() == typeId)
+ return type->fromObject(obj);
+ else
+ return QVariant();
+}
+
+const QMetaObject *QmlMetaType::rawMetaObjectForType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(id);
+ if (type && type->typeId() == id)
+ return type->baseMetaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::rawMetaObjectForType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->baseMetaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::metaObjectForType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ lock.unlock();
+
+ if (type && type->typeId() == id)
+ return type->metaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::metaObjectForType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->nameToType.value(name);
+ lock.unlock();
+
+ if (type)
+ return type->metaObject();
+ else
+ return 0;
+}
+
+int QmlMetaType::type(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->typeId();
+ else
+ return 0;
+}
+
+int QmlMetaType::attachedPropertiesFuncId(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type && type->attachedPropertiesFunction())
+ return type->index();
+ else
+ return -1;
+}
+
+int QmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->metaObjectToType.value(mo);
+ if (type && type->attachedPropertiesFunction())
+ return type->index();
+ else
+ return -1;
+}
+
+QmlAttachedPropertiesFunc QmlMetaType::attachedPropertiesFuncById(int id)
+{
+ if (id < 0)
+ return 0;
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return data->types.at(id)->attachedPropertiesFunction();
+}
+
+QmlAttachedPropertiesFunc
+QmlMetaType::attachedPropertiesFunc(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->attachedPropertiesFunction();
+ else
+ return 0;
+}
+
+QMetaProperty QmlMetaType::defaultProperty(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultProperty");
+ if (-1 == idx)
+ return QMetaProperty();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaProperty();
+
+ idx = metaObject->indexOfProperty(info.value());
+ if (-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+QMetaProperty QmlMetaType::defaultProperty(QObject *obj)
+{
+ if (!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultProperty(metaObject);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultMethod");
+ if (-1 == idx)
+ return QMetaMethod();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaMethod();
+
+ idx = metaObject->indexOfMethod(info.value());
+ if (-1 == idx)
+ return QMetaMethod();
+
+ return metaObject->method(idx);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(QObject *obj)
+{
+ if (!obj)
+ return QMetaMethod();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultMethod(metaObject);
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const QByteArray &bname)
+{
+ return property(obj, bname.constData());
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const char *name)
+{
+ if (!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+
+ int idx = metaObject->indexOfProperty(name);
+ if (-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+bool QmlMetaType::isObject(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
+}
+
+bool QmlMetaType::isInterface(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
+}
+
+const char *QmlMetaType::interfaceIId(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->isInterface() && type->typeId() == userType)
+ return type->interfaceIId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::isObject(const QMetaObject *mo)
+{
+ // ### Huh?
+ while(mo) {
+ if (mo == &QObject::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+bool QmlMetaType::isQmlList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->qmllists.size() && data->qmllists.testBit(userType);
+}
+
+bool QmlMetaType::isList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
+}
+
+bool QmlMetaType::isList(const QVariant &v)
+{
+ return (v.type() == QVariant::UserType && isList(v.userType()));
+}
+
+int QmlMetaType::listCount(const QVariant &v)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listCount(v);
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::listAt(const QVariant &v, int idx)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listAt(v, idx);
+ else
+ return 0;
+}
+
+/*!
+ A custom string convertor allows you to specify a function pointer that
+ returns a variant of \a type. For example, if you have written your own icon
+ class that you want to support as an object property assignable in QML:
+
+ \code
+ int type = qRegisterMetaType<SuperIcon>("SuperIcon");
+ QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
+ \endcode
+
+ The function pointer must be of the form:
+ \code
+ QVariant (*StringConverter)(const QString &);
+ \endcode
+ */
+void QmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
+{
+ QWriteLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ if (data->stringConverters.contains(type))
+ return;
+ data->stringConverters.insert(type, converter);
+}
+
+/*!
+ Return the custom string converter for \a type, previously installed through
+ registerCustomStringConverter()
+ */
+QmlMetaType::StringConverter QmlMetaType::customStringConverter(int type)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ return data->stringConverters.value(type);
+}
+
+QmlType *QmlMetaType::qmlType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.value(name);
+}
+
+QmlType *QmlMetaType::qmlType(const QMetaObject *metaObject)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->metaObjectToType.value(metaObject);
+}
+
+QList<QByteArray> QmlMetaType::qmlTypeNames()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.keys();
+}
+
+/*!
+ Copies \a copy into \a data, assuming they both are of type \a type. If
+ \a copy is zero, a default type is copied. Returns true if the copy was
+ successful and false if not.
+
+ \note This should move into QMetaType once complete
+
+*/
+bool QmlMetaType::copy(int type, void *data, const void *copy)
+{
+ if (copy) {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = *static_cast<const long*>(copy);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = *static_cast<const int*>(copy);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = *static_cast<const short*>(copy);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = *static_cast<const char*>(copy);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = *static_cast<const ulong*>(copy);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = *static_cast<const uint*>(copy);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = *static_cast<const qlonglong*>(copy);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = *static_cast<const qulonglong*>(copy);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = *static_cast<const ushort*>(copy);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = *static_cast<const uchar*>(copy);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = *static_cast<const bool*>(copy);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = *static_cast<const float*>(copy);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = *static_cast<const double*>(copy);
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = *static_cast<const NS(QChar)*>(copy);
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = *static_cast<const NS(QVariantMap)*>(copy);
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = *static_cast<const NS(QVariantHash)*>(copy);
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = *static_cast<const NS(QVariantList)*>(copy);
+ return true;
+#endif
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = *static_cast<const NS(QByteArray)*>(copy);
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = *static_cast<const NS(QString)*>(copy);
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = *static_cast<const NS(QStringList)*>(copy);
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = *static_cast<const NS(QBitArray)*>(copy);
+ return true;
+#endif
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = *static_cast<const NS(QDate)*>(copy);
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = *static_cast<const NS(QTime)*>(copy);
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = *static_cast<const NS(QDateTime)*>(copy);
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = *static_cast<const NS(QUrl)*>(copy);
+ return true;
+#endif
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = *static_cast<const NS(QLocale)*>(copy);
+ return true;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = *static_cast<const NS(QRect)*>(copy);
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = *static_cast<const NS(QRectF)*>(copy);
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = *static_cast<const NS(QSize)*>(copy);
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = *static_cast<const NS(QSizeF)*>(copy);
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = *static_cast<const NS(QLine)*>(copy);
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = *static_cast<const NS(QLineF)*>(copy);
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = *static_cast<const NS(QPoint)*>(copy);
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = *static_cast<const NS(QPointF)*>(copy);
+ return true;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+ default:
+ ;
+ }
+ } else {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = 0;
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = long(0);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = int(0);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = short(0);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = char(0);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = ulong(0);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = uint(0);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = qlonglong(0);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = qulonglong(0);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = ushort(0);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = uchar(0);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = bool(false);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = float(0);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = double();
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = NS(QChar)();
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = NS(QVariantMap)();
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = NS(QVariantHash)();
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = NS(QVariantList)();
+ return true;
+#endif
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = NS(QByteArray)();
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = NS(QString)();
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = NS(QStringList)();
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = NS(QBitArray)();
+ return true;
+#endif
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = NS(QDate)();
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = NS(QTime)();
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = NS(QDateTime)();
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = NS(QUrl)();
+ return true;
+#endif
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = NS(QLocale)();
+ return true;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = NS(QRect)();
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = NS(QRectF)();
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = NS(QSize)();
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = NS(QSizeF)();
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = NS(QLine)();
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = NS(QLineF)();
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = NS(QPoint)();
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = NS(QPointF)();
+ return true;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+ default:
+ ;
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h
new file mode 100644
index 0000000..d10a0f0
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.h
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETATYPE_H
+#define QMLMETATYPE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qbitarray.h>
+#include <QtDeclarative/qmlprivate.h>
+#include <QtDeclarative/qmlparserstatus.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlType;
+class QmlCustomParser;
+class Q_DECLARATIVE_EXPORT QmlMetaType
+{
+public:
+ static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *);
+ static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *);
+
+ static bool copy(int type, void *data, const void *copy = 0);
+
+ static QList<QByteArray> qmlTypeNames();
+
+ static QmlType *qmlType(const QByteArray &);
+ static QmlType *qmlType(const QMetaObject *);
+
+ static QMetaProperty defaultProperty(const QMetaObject *);
+ static QMetaProperty defaultProperty(QObject *);
+ static QMetaMethod defaultMethod(const QMetaObject *);
+ static QMetaMethod defaultMethod(QObject *);
+ static QMetaProperty property(QObject *, const QByteArray &);
+ static QMetaProperty property(QObject *, const char *);
+ static QObject *toQObject(const QVariant &);
+ static int qmlParserStatusCast(int);
+ static int listType(int);
+ static int type(const QByteArray &);
+ static int type(const QString &);
+ static bool clear(const QVariant &);
+ static bool append(const QVariant &, const QVariant &);
+ static QVariant fromObject(QObject *, int type);
+ static QObject *create(const QByteArray &);
+ static const QMetaObject *rawMetaObjectForType(const QByteArray &);
+ static const QMetaObject *rawMetaObjectForType(int);
+ static const QMetaObject *metaObjectForType(const QByteArray &);
+ static const QMetaObject *metaObjectForType(int);
+ static int attachedPropertiesFuncId(const QByteArray &);
+ static int attachedPropertiesFuncId(const QMetaObject *);
+ static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int);
+ static QmlAttachedPropertiesFunc attachedPropertiesFunc(const QByteArray &);
+
+ static bool isInterface(int);
+ static const char *interfaceIId(int);
+ static bool isObject(int);
+ static bool isObject(const QMetaObject *);
+ static bool isList(int);
+ static bool isList(const QVariant &);
+ static bool isQmlList(int);
+ static int qmlListType(int);
+ static int listCount(const QVariant &);
+ static QVariant listAt(const QVariant &, int);
+
+ typedef QVariant (*StringConverter)(const QString &);
+ static void registerCustomStringConverter(int, StringConverter);
+ static StringConverter customStringConverter(int);
+};
+
+class QmlTypePrivate;
+class Q_DECLARATIVE_EXPORT QmlType
+{
+public:
+ QByteArray typeName() const;
+ QByteArray qmlTypeName() const;
+
+ QByteArray hash() const;
+
+ QObject *create() const;
+
+ QmlCustomParser *customParser() const;
+
+ bool isInterface() const;
+ int typeId() const;
+ int qListTypeId() const;
+ int qmlListTypeId() const;
+
+ void listClear(const QVariant &);
+ void listAppend(const QVariant &, const QVariant &);
+ QVariant listAt(const QVariant &, int);
+ int listCount(const QVariant &);
+
+ const QMetaObject *metaObject() const;
+ const QMetaObject *baseMetaObject() const;
+
+ QmlAttachedPropertiesFunc attachedPropertiesFunction() const;
+ const QMetaObject *attachedPropertiesType() const;
+
+ int parserStatusCast() const;
+ QVariant fromObject(QObject *) const;
+ const char *interfaceIId() const;
+
+ int index() const;
+private:
+ friend class QmlMetaType;
+ friend class QmlTypePrivate;
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int);
+ QmlType(int, int, int, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *);
+ ~QmlType();
+
+ QmlTypePrivate *d;
+};
+
+template<typename T>
+int qmlRegisterType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T>
+int qmlRegisterType(const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMo =
+ QmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+ attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0,
+ &T::staticMetaObject, attached, attachedMo,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMo =
+ QmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+ attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ qmlName,
+ &T::staticMetaObject,
+ attached, attachedMo,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ &QmlPrivate::CreateParent<E>::create,
+ &E::staticMetaObject, 0);
+}
+
+template<typename T>
+int qmlRegisterInterface(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerInterface(ids,
+ QmlPrivate::list_interface_op<T>,
+ qobject_interface_iid<T *>());
+}
+
+template<typename T>
+int qmlRegisterCustomType(const char *qmlName, const char *typeName, QmlCustomParser *parser)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0, parser);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETATYPE_H
+
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
new file mode 100644
index 0000000..fadfbb1
--- /dev/null
+++ b/src/declarative/qml/qmlparser.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlparser_p.h"
+#include <QStack>
+#include <qmlpropertyvaluesource.h>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <private/qmlvme_p.h>
+#include <qmlbindablevalue.h>
+#include <qfxperf.h>
+#include <qml.h>
+#include "private/qmlcomponent_p.h"
+#include <qmlcomponent.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <private/qmlvmemetaobject_p.h>
+#include <private/qmlcompiler_p.h>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+QmlParser::Object::Object()
+: type(-1), metatype(0), extObjectData(0), defaultProperty(0)
+{
+}
+
+QmlParser::Object::~Object()
+{
+ if (defaultProperty) defaultProperty->release();
+ foreach(Property *prop, properties)
+ prop->release();
+}
+
+const QMetaObject *Object::metaObject() const
+{
+ if (extObjectData && metatype)
+ return &extObject;
+ else
+ return metatype;
+}
+
+QmlParser::Property *Object::getDefaultProperty()
+{
+ if (!defaultProperty) {
+ defaultProperty = new Property;
+ defaultProperty->parent = this;
+ }
+ return defaultProperty;
+}
+
+Property *QmlParser::Object::getProperty(const QByteArray &name, bool create)
+{
+ if (!properties.contains(name)) {
+ if (create) {
+ Property *property = new Property(name);
+ property->parent = this;
+ properties.insert(name, property);
+ } else {
+ return 0;
+ }
+ }
+ return properties[name];
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty()
+: isDefaultProperty(false), type(Variant), defaultValue(0)
+{
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o)
+: isDefaultProperty(o.isDefaultProperty),
+ type(o.type),
+ name(o.name),
+ defaultValue(o.defaultValue)
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal()
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
+: name(o.name)
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot()
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o)
+: name(o.name), body(o.body)
+{
+}
+
+void QmlParser::Object::dump(int indent) const
+{
+ QByteArray ba(indent * 4, ' ');
+ if (type != -1) {
+ qWarning() << ba.constData() << "Object:" << typeName;
+ } else {
+ qWarning() << ba.constData() << "Object: fetched";
+ }
+
+ for (QHash<QByteArray, Property *>::ConstIterator iter = properties.begin();
+ iter != properties.end();
+ ++iter) {
+ qWarning() << ba.constData() << " Property" << iter.key();
+ (*iter)->dump(indent + 1);
+ }
+
+ if (defaultProperty) {
+ qWarning() << ba.constData() << " Default property";
+ defaultProperty->dump(indent + 1);
+ }
+}
+
+QmlParser::Property::Property()
+: parent(0), type(0), index(-1), value(0), isDefault(true)
+{
+}
+
+QmlParser::Property::Property(const QByteArray &n)
+: parent(0), type(0), index(-1), value(0), name(n), isDefault(false)
+{
+}
+
+QmlParser::Property::~Property()
+{
+ foreach(Value *value, values)
+ value->release();
+ if (value) value->release();
+}
+
+Object *QmlParser::Property::getValue()
+{
+ if (!value) value = new Object;
+ return value;
+}
+
+void QmlParser::Property::addValue(Value *v)
+{
+ values << v;
+}
+
+void QmlParser::Property::dump(int indent) const
+{
+ QByteArray ba(indent * 4, ' ');
+ for (int ii = 0; ii < values.count(); ++ii)
+ values.at(ii)->dump(indent);
+ if (value)
+ value->dump(indent);
+}
+
+QmlParser::Value::Value()
+: type(Unknown), object(0)
+{
+}
+
+QmlParser::Value::~Value()
+{
+ if (object) object->release();
+}
+
+void QmlParser::Value::dump(int indent) const
+{
+ QByteArray type;
+ switch(this->type) {
+ default:
+ case Value::Unknown:
+ type = "Unknown";
+ break;
+ case Value::Literal:
+ type = "Literal";
+ break;
+ case Value::PropertyBinding:
+ type = "PropertyBinding";
+ break;
+ case Value::ValueSource:
+ type = "ValueSource";
+ break;
+ case Value::CreatedObject:
+ type = "CreatedObject";
+ break;
+ case Value::SignalObject:
+ type = "SignalObject";
+ break;
+ case Value::SignalExpression:
+ type = "SignalExpression";
+ break;
+ case Value::Component:
+ type = "Component";
+ break;
+ case Value::Id:
+ type = "Id";
+ break;
+ }
+
+ QByteArray primType;
+ switch(this->value.type()) {
+ default:
+ case Variant::Invalid:
+ primType = "Invalid";
+ break;
+ case Variant::Boolean:
+ primType = "Boolean";
+ break;
+ case Variant::Number:
+ primType = "Number";
+ break;
+ case Variant::String:
+ primType = "String";
+ break;
+ case Variant::Script:
+ primType = "Script";
+ break;
+ }
+
+ QByteArray ba(indent * 4, ' ');
+ if (object) {
+ qWarning() << ba.constData() << "Value (" << type << "):";
+ object->dump(indent + 1);
+ } else {
+ qWarning() << ba.constData() << "Value (" << type << "):" << primType.constData() << primitive();
+ }
+}
+
+QmlParser::Variant::Variant()
+: t(Invalid) {}
+
+QmlParser::Variant::Variant(const Variant &o)
+: t(o.t), d(o.d), s(o.s)
+{
+}
+
+QmlParser::Variant::Variant(bool v)
+: t(Boolean), b(v)
+{
+}
+
+QmlParser::Variant::Variant(double v, const QString &asWritten)
+: t(Number), d(v), s(asWritten)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v)
+: t(String), s(v)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v, JavaScript::AST::Node *n)
+: t(Script), n(n), s(v)
+{
+}
+
+QmlParser::Variant &QmlParser::Variant::operator=(const Variant &o)
+{
+ t = o.t;
+ d = o.d;
+ s = o.s;
+ return *this;
+}
+
+QmlParser::Variant::Type QmlParser::Variant::type() const
+{
+ return t;
+}
+
+bool QmlParser::Variant::asBoolean() const
+{
+ return b;
+}
+
+QString QmlParser::Variant::asString() const
+{
+ return s;
+}
+
+double QmlParser::Variant::asNumber() const
+{
+ return d;
+}
+
+QString QmlParser::Variant::asScript() const
+{
+ switch(type()) {
+ default:
+ case Invalid:
+ return QString();
+ case Boolean:
+ return b?QLatin1String("true"):QLatin1String("false");
+ case Number:
+ if (s.isEmpty())
+ return QString::number(d);
+ else
+ return s;
+ case String:
+ case Script:
+ return s;
+ }
+}
+
+JavaScript::AST::Node *QmlParser::Variant::asAST() const
+{
+ if (type() == Script)
+ return n;
+ else
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
new file mode 100644
index 0000000..0fdd26b
--- /dev/null
+++ b/src/declarative/qml/qmlparser_p.h
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPARSER_P_H
+#define QMLPARSER_P_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qml.h>
+#include <private/qmlrefcount_p.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+namespace JavaScript { namespace AST { class Node; } }
+
+/*
+ XXX
+
+ These types are created (and owned) by the QmlXmlParser and consumed by the
+ QmlCompiler. During the compilation phase the compiler will update some of
+ the fields for both its own use and for the use of the upcoming QmlDom API.
+
+ The types are part of the generic sounding "QmlParser" namespace for legacy
+ reasons (there used to be more in this namespace) and will be cleaned up and
+ migrated into a more appropriate location shortly.
+*/
+namespace QmlParser
+{
+ struct Location
+ {
+ Location() : line(-1), column(-1) {}
+ int line;
+ int column;
+ };
+
+ struct LocationRange
+ {
+ LocationRange() : offset(0), length(0) {}
+ quint32 offset;
+ quint32 length;
+ };
+
+ struct LocationSpan
+ {
+ Location start;
+ Location end;
+ LocationRange range;
+ };
+
+ class Property;
+ class Object : public QmlRefCount
+ {
+ public:
+ Object();
+ virtual ~Object();
+
+ // Type of the object. The integer is an index into the
+ // QmlCompiledData::types array, or -1 if the object is a fetched
+ // object.
+ int type;
+ // The name of this type
+ QByteArray typeName;
+ // The id assigned to the object (if any).
+ QByteArray id;
+ // Custom parsed data
+ QByteArray custom;
+ // Returns the metaobject for this type, or 0 if not available.
+ // Internally selectd between the metatype and extObject variables
+ const QMetaObject *metaObject() const;
+
+ // The compile time metaobject for this type
+ const QMetaObject *metatype;
+ // The synthesized metaobject, if QML added signals or properties to
+ // this type. Otherwise null
+ QMetaObject *extObjectData;
+ QAbstractDynamicMetaObject extObject;
+
+ Property *getDefaultProperty();
+ Property *getProperty(const QByteArray &name, bool create=true);
+
+ Property *defaultProperty;
+ QHash<QByteArray, Property *> properties;
+
+ LocationSpan location;
+
+ struct DynamicProperty {
+ DynamicProperty();
+ DynamicProperty(const DynamicProperty &);
+
+ enum Type { Variant, Int, Bool, Real, String, Color, Date };
+
+ bool isDefaultProperty;
+ Type type;
+ QByteArray name;
+ QmlParser::Property *defaultValue;
+ };
+ struct DynamicSignal {
+ DynamicSignal();
+ DynamicSignal(const DynamicSignal &);
+
+ QByteArray name;
+ };
+ struct DynamicSlot {
+ DynamicSlot();
+ DynamicSlot(const DynamicSlot &);
+
+ QByteArray name;
+ QString body;
+ };
+
+ // The list of dynamic properties
+ QList<DynamicProperty> dynamicProperties;
+ // The list of dynamic signals
+ QList<DynamicSignal> dynamicSignals;
+ // The list of dynamic slots
+ QList<DynamicSlot> dynamicSlots;
+
+ void dump(int = 0) const;
+ };
+
+ class Variant
+ {
+ public:
+ enum Type {
+ Invalid,
+ Boolean,
+ Number,
+ String,
+ Script
+ };
+
+ Variant();
+ Variant(const Variant &);
+ Variant(bool);
+ Variant(double, const QString &asWritten=QString());
+ Variant(const QString &);
+ Variant(const QString &, JavaScript::AST::Node *);
+ Variant &operator=(const Variant &);
+
+ Type type() const;
+
+ bool isBoolean() const { return type() == Boolean; }
+ bool isNumber() const { return type() == Number; }
+ bool isString() const { return type() == String; }
+ bool isScript() const { return type() == Script; }
+
+ bool asBoolean() const;
+ QString asString() const;
+ double asNumber() const;
+ QString asScript() const;
+ JavaScript::AST::Node *asAST() const;
+
+ private:
+ Type t;
+ union {
+ bool b;
+ double d;
+ JavaScript::AST::Node *n;
+ };
+ QString s;
+ };
+
+ class Value : public QmlRefCount
+ {
+ public:
+ Value();
+ virtual ~Value();
+
+ enum Type {
+ // The type of this value assignment is not yet known
+ Unknown,
+ // This is used as a literal property assignment
+ Literal,
+ // This is used as a property binding assignment
+ PropertyBinding,
+ // This is used as a QmlPropertyValueSource assignment
+ ValueSource,
+ // This is used as a property QObject assignment
+ CreatedObject,
+ // This is used as a signal object assignment
+ SignalObject,
+ // This is used as a signal expression assignment
+ SignalExpression,
+ // This is used as an implicit component creation
+ Component,
+ // This is used as an id assignment only
+ Id
+ };
+ Type type;
+
+ // ### Temporary
+ QString primitive() const { return value.asScript(); }
+
+ // Primitive value
+ Variant value;
+ // Object value
+ Object *object;
+
+ LocationSpan location;
+
+ void dump(int = 0) const;
+ };
+
+ class Property : public QmlRefCount
+ {
+ public:
+ Property();
+ Property(const QByteArray &n);
+ virtual ~Property();
+
+ // The Object to which this property is attached
+ Object *parent;
+
+ Object *getValue();
+ void addValue(Value *v);
+
+ // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
+ // unknown.
+ int type;
+ // The metaobject index of this property, or -1 if unknown.
+ int index;
+
+ // The list of values assigned to this property. Content in values
+ // and value are mutually exclusive
+ QList<Value *> values;
+ // The accessed property. This is used to represent dot properties.
+ // Content in value and values are mutually exclusive.
+ Object *value;
+ // The property name
+ QByteArray name;
+ // True if this property was accessed as the default property.
+ bool isDefault;
+
+ LocationSpan location;
+ LocationRange listValueRange;
+
+ void dump(int = 0) const;
+ };
+}
+Q_DECLARE_METATYPE(QmlParser::Variant)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPARSER_P_H
diff --git a/src/declarative/qml/qmlparserstatus.cpp b/src/declarative/qml/qmlparserstatus.cpp
new file mode 100644
index 0000000..fceac05
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlparserstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlParserStatus
+ \brief The QmlParserStatus class provides updates on the parser state.
+*/
+
+/*! \internal */
+QmlParserStatus::QmlParserStatus()
+: d(0)
+{
+}
+
+/*! \internal */
+QmlParserStatus::~QmlParserStatus()
+{
+ if(d)
+ (*d) = 0;
+}
+
+/*!
+ Invoked after class creation, but before any properties have been set.
+*/
+void QmlParserStatus::classBegin()
+{
+}
+
+/*!
+ Invoked after all properties have been set to their static values. At this
+ point bindings are still to be evaluated.
+*/
+void QmlParserStatus::classComplete()
+{
+}
+
+/*!
+ Invoked after the root component that caused this instantiation has
+ completed construction. At this point all static values and binding values
+ have been assigned to the class.
+*/
+void QmlParserStatus::componentComplete()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h
new file mode 100644
index 0000000..7c2e141
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPARSERSTATUS_H
+#define QMLPARSERSTATUS_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlParserStatus
+{
+public:
+ QmlParserStatus();
+ virtual ~QmlParserStatus();
+
+ virtual void classBegin();
+ virtual void classComplete();
+ virtual void componentComplete();
+
+private:
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlEnginePrivate;
+ QmlParserStatus **d;
+};
+Q_DECLARE_INTERFACE(QmlParserStatus, "com.trolltech.qml.QmlParserStatus")
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPARSERSTATUS_H
diff --git a/src/declarative/qml/qmlprivate.cpp b/src/declarative/qml/qmlprivate.cpp
new file mode 100644
index 0000000..21b19e8
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlprivate.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlPrivate::InstanceType::InstanceType(int) {}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlprivate.h b/src/declarative/qml/qmlprivate.h
new file mode 100644
index 0000000..3f41fb7
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.h
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPRIVATE_H
+#define QMLPRIVATE_H
+
+#include <QtCore/qglobal.h>
+#ifndef Q_OS_WIN32
+#include <stdint.h>
+#endif
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+typedef QObject *(*QmlAttachedPropertiesFunc)(QObject *);
+
+namespace QmlPrivate
+{
+ class ListInterface
+ {
+ public:
+ virtual ~ListInterface() {}
+ virtual int type() const = 0;
+ virtual void append(void *) = 0;
+ virtual void insert(int, void *) = 0;
+ virtual void removeAt(int) = 0;
+ virtual void at(int, void *) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ };
+
+ enum ListOp { Append, Set, Insert, Prepend, Length, FromObject,
+ Object, Create, Value, Clear };
+
+ template<typename T>
+ int list_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_nocreate_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_interface_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<class From, class To, int N>
+ struct StaticCastSelectorClass
+ {
+ static inline int cast() { return -1; }
+ };
+
+ template<class From, class To>
+ struct StaticCastSelectorClass<From, To, sizeof(int)>
+ {
+#ifndef Q_OS_SYMBIAN
+ static inline int cast() { return (int)((intptr_t)static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+#else
+ static inline int cast() { return (int)(static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+#endif
+ };
+
+ template<class From, class To>
+ struct StaticCastSelector
+ {
+ typedef int yes_type;
+ typedef char no_type;
+
+ static yes_type check(To *);
+ static no_type check(...);
+
+ static inline int cast()
+ {
+ return StaticCastSelectorClass<From, To, sizeof(check((From *)0))>::cast();
+ }
+ };
+
+ template<typename T, typename Sign = T *(*)(QObject *)>
+ struct has_qmlAttachedProperties
+ {
+ template <typename U, U> struct type_check;
+ template <typename _1> static char check(type_check<Sign, &_1::qmlAttachedProperties> *);
+ template <typename > static int check(...);
+ static bool const value = sizeof(check<T>(0)) == sizeof(char);
+ };
+
+ template<typename T, int N>
+ class AttachedPropertySelector
+ {
+ public:
+ static inline QmlAttachedPropertiesFunc func() { return 0; }
+ static inline const QMetaObject *metaObject() { return 0; }
+ };
+ template<typename T>
+ class AttachedPropertySelector<T, 1>
+ {
+ static inline QObject *attachedProperties(QObject *obj) {
+ return T::qmlAttachedProperties(obj);
+ }
+ template<typename ReturnType>
+ static inline const QMetaObject *attachedPropertiesMetaObject(ReturnType *(*)(QObject *)) {
+ return &ReturnType::staticMetaObject;
+ }
+ public:
+ static inline QmlAttachedPropertiesFunc func() {
+ return &attachedProperties;
+ }
+ static inline const QMetaObject *metaObject() {
+ return attachedPropertiesMetaObject(&T::qmlAttachedProperties);
+ }
+ };
+
+ template<typename T>
+ inline QmlAttachedPropertiesFunc attachedPropertiesFunc()
+ {
+ return AttachedPropertySelector<T, has_qmlAttachedProperties<T>::value >::func();
+ }
+
+ template<typename T>
+ inline const QMetaObject *attachedPropertiesMetaObject()
+ {
+ return AttachedPropertySelector<T, has_qmlAttachedProperties<T>::value >::metaObject();
+ }
+
+ struct MetaTypeIds {
+ int typeId;
+ int listId;
+ int qmlListId;
+ };
+ typedef int (*Func)(QmlPrivate::ListOp, int, const QVariant &, const QVariant &, void **);
+ typedef QObject *(*CreateFunc)(QObject *);
+
+ template<typename T>
+ struct CreateParent {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+
+ template<typename T>
+ struct CreateNoParent {
+ static QObject *create() {
+ return new T;
+ }
+ };
+
+ struct Q_DECLARATIVE_EXPORT InstanceType {
+ InstanceType(int);
+ };
+
+ template<typename T>
+ struct Define {
+ static InstanceType instance;
+ };
+
+ template<typename T>
+ struct ExtCreate {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+}
+
+template<typename T>
+int QmlPrivate::list_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ if (op == QmlPrivate::Create) {
+ QObject *obj = static_cast<QObject *>(new T);
+ *((QObject **)out) = obj;
+ return 0;
+ }
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_nocreate_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_interface_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ break;
+ case QmlPrivate::FromObject:
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+
+#endif // QMLPRIVATE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlpropertyvaluesource.cpp b/src/declarative/qml/qmlpropertyvaluesource.cpp
new file mode 100644
index 0000000..18092c8
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertyvaluesource.h"
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \class QmlPropertyValueSource
+ \brief The QmlPropertyValueSource class is inherited by property value sources such as animations and bindings.
+ */
+QML_DEFINE_NOCREATE_TYPE(QmlPropertyValueSource)
+
+/*!
+ Constructs a QmlPropertyValueSource with parent \a parent.
+*/
+QmlPropertyValueSource::QmlPropertyValueSource(QObject *parent)
+ : QObject(parent)
+
+{
+}
+
+/*!
+ \internal
+ */
+QmlPropertyValueSource::QmlPropertyValueSource(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Set the target \a property for the value source. This method will
+ be called by the QML engine when assigning a value source.
+
+ The default implementation does nothing.
+*/
+void QmlPropertyValueSource::setTarget(const QmlMetaProperty &property)
+{
+ Q_UNUSED(property);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvaluesource.h b/src/declarative/qml/qmlpropertyvaluesource.h
new file mode 100644
index 0000000..9cef150
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVALUESOURCE_H
+#define QMLPROPERTYVALUESOURCE_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtCore/QObject>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QObjectPrivate;
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueSource : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ QmlPropertyValueSource(QObject *parent);
+ virtual void setTarget(const QmlMetaProperty &);
+
+protected:
+ QmlPropertyValueSource(QObjectPrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QmlPropertyValueSource)
+};
+QML_DECLARE_TYPE(QmlPropertyValueSource)
+
+#endif // QMLPROPERTYVALUESOURCE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlproxymetaobject.cpp b/src/declarative/qml/qmlproxymetaobject.cpp
new file mode 100644
index 0000000..d24c5c4
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlproxymetaobject_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QmlProxyMetaObject::QmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
+: metaObjects(mList), proxies(0), parent(0), object(obj)
+{
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ qWarning() << "QmlProxyMetaObject" << obj->metaObject()->className();
+#endif
+
+ *static_cast<QMetaObject *>(this) = *metaObjects->last().metaObject;
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+
+ op->metaObject = this;
+
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ const QMetaObject *mo = obj->metaObject();
+ while(mo) {
+ qWarning() << " " << mo->className();
+ mo = mo->superClass();
+ }
+#endif
+}
+
+QmlProxyMetaObject::~QmlProxyMetaObject()
+{
+ if (parent)
+ delete parent;
+ parent = 0;
+
+ if (proxies)
+ delete [] proxies;
+ proxies = 0;
+}
+
+int QmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if ((c == QMetaObject::ReadProperty ||
+ c == QMetaObject::WriteProperty) &&
+ id >= metaObjects->last().propertyOffset) {
+
+ for (int ii = 0; ii < metaObjects->count(); ++ii) {
+ const ProxyData &data = metaObjects->at(ii);
+ if (id >= data.propertyOffset) {
+ if (!proxies) {
+ proxies = new QObject*[metaObjects->count()];
+ ::memset(proxies, 0,
+ sizeof(QObject *) * metaObjects->count());
+ }
+
+ if (!proxies[ii])
+ proxies[ii] = data.createFunc(object);
+
+ int proxyOffset = proxies[ii]->metaObject()->propertyOffset();
+ int proxyId = id - data.propertyOffset + proxyOffset;
+
+ return proxies[ii]->qt_metacall(c, proxyId, a);
+ }
+ }
+ }
+
+ if (parent)
+ return parent->metaCall(c, id, a);
+ else
+ return object->qt_metacall(c, id, a);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlproxymetaobject_p.h b/src/declarative/qml/qmlproxymetaobject_p.h
new file mode 100644
index 0000000..0ffa365
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROXYMETAOBJECT_P_H
+#define QMLPROXYMETAOBJECT_P_H
+
+#include <QtCore/QMetaObject>
+#include <QtCore/QObject>
+#include <private/qmetaobjectbuilder_p.h>
+#include <private/qobject_p.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlProxyMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ struct ProxyData {
+ typedef QObject *(*CreateFunc)(QObject *);
+ QMetaObject *metaObject;
+ CreateFunc createFunc;
+ int propertyOffset;
+ };
+
+ QmlProxyMetaObject(QObject *, QList<ProxyData> *);
+ virtual ~QmlProxyMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QList<ProxyData> *metaObjects;
+ QObject **proxies;
+
+ QAbstractDynamicMetaObject *parent;
+ QObject *object;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROXYMETAOBJECT_P_H
+
diff --git a/src/declarative/qml/qmlrefcount.cpp b/src/declarative/qml/qmlrefcount.cpp
new file mode 100644
index 0000000..8f71f1b
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlrefcount_p.h"
+
+QmlRefCount::QmlRefCount()
+: refCount(1)
+{
+}
+
+QmlRefCount::~QmlRefCount()
+{
+}
+
+void QmlRefCount::addref()
+{
+ Q_ASSERT(refCount > 0);
+ ++refCount;
+}
+
+void QmlRefCount::release()
+{
+ Q_ASSERT(refCount > 0);
+ --refCount;
+ if (refCount == 0)
+ delete this;
+}
+
diff --git a/src/declarative/qml/qmlrefcount_p.h b/src/declarative/qml/qmlrefcount_p.h
new file mode 100644
index 0000000..1355c86
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLREFCOUNT_P_H
+#define QMLREFCOUNT_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlRefCount
+{
+public:
+ QmlRefCount();
+ virtual ~QmlRefCount();
+ void addref();
+ void release();
+
+private:
+ int refCount;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLREFCOUNT_P_H
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
new file mode 100644
index 0000000..31a20be
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -0,0 +1,860 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlscriptparser_p.h"
+#include "qmlparser_p.h"
+
+#include "parser/javascriptengine_p.h"
+#include "parser/javascriptparser_p.h"
+#include "parser/javascriptlexer_p.h"
+#include "parser/javascriptnodepool_p.h"
+#include "parser/javascriptastvisitor_p.h"
+#include "parser/javascriptast_p.h"
+
+#include "rewriter/textwriter_p.h"
+
+#include <QStack>
+#include <QCoreApplication>
+#include <QtDebug>
+
+#include <qfxperf.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace JavaScript;
+using namespace QmlParser;
+
+namespace {
+
+class RewriteNumericLiterals: protected AST::Visitor
+{
+ unsigned _position;
+ TextWriter *_writer;
+
+public:
+ QString operator()(QString code, unsigned position, AST::Node *node)
+ {
+ TextWriter w;
+ _writer = &w;
+ _position = position;
+
+ AST::Node::acceptChild(node, this);
+
+ w.write(&code);
+
+ return code;
+ }
+
+protected:
+ using AST::Visitor::visit;
+
+ virtual bool visit(AST::NumericLiteral *node)
+ {
+ if (node->suffix != AST::NumericLiteral::noSuffix) {
+ const int suffixLength = AST::NumericLiteral::suffixLength[node->suffix];
+ const char *suffixSpell = AST::NumericLiteral::suffixSpell[node->suffix];
+ QString pre;
+ pre += QLatin1String("qmlNumberFrom");
+ pre += QChar(QLatin1Char(suffixSpell[0])).toUpper();
+ pre += QLatin1String(&suffixSpell[1]);
+ pre += QLatin1Char('(');
+ _writer->replace(node->literalToken.begin() - _position, 0, pre);
+ _writer->replace(node->literalToken.end() - _position - suffixLength,
+ suffixLength,
+ QLatin1String(")"));
+ }
+
+ return false;
+ }
+};
+
+class ProcessAST: protected AST::Visitor
+{
+ struct State {
+ State() : object(0), property(0) {}
+ State(Object *o) : object(o), property(0) {}
+ State(Object *o, Property *p) : object(o), property(p) {}
+
+ Object *object;
+ Property *property;
+ };
+
+ struct StateStack : public QStack<State>
+ {
+ void pushObject(Object *obj)
+ {
+ push(State(obj));
+ }
+
+ void pushProperty(const QString &name, const LocationSpan &location)
+ {
+ const State &state = top();
+ if (state.property) {
+ State s(state.property->getValue(),
+ state.property->getValue()->getProperty(name.toLatin1()));
+ s.property->location = location;
+ push(s);
+ } else {
+ State s(state.object,
+ state.object->getProperty(name.toLatin1()));
+
+ s.property->location = location;
+ push(s);
+ }
+ }
+ };
+
+public:
+ ProcessAST(QmlScriptParser *parser);
+ virtual ~ProcessAST();
+
+ void operator()(const QString &code, AST::Node *node);
+
+protected:
+ Object *defineObjectBinding(AST::UiQualifiedId *propertyName,
+ AST::UiQualifiedId *objectTypeName,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+
+ Object *defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+
+ QmlParser::Variant getVariant(AST::ExpressionNode *expr);
+
+ LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
+ LocationSpan location(AST::UiQualifiedId *);
+
+ using AST::Visitor::visit;
+ using AST::Visitor::endVisit;
+
+ virtual bool visit(AST::UiProgram *node);
+ virtual bool visit(AST::UiImport *node);
+ virtual bool visit(AST::UiObjectDefinition *node);
+ virtual bool visit(AST::UiPublicMember *node);
+ virtual bool visit(AST::UiObjectBinding *node);
+
+ virtual bool visit(AST::UiScriptBinding *node);
+ virtual bool visit(AST::UiArrayBinding *node);
+ virtual bool visit(AST::UiSourceElement *node);
+
+ void accept(AST::Node *node);
+
+ QString asString(AST::UiQualifiedId *node) const;
+
+ const State state() const;
+ Object *currentObject() const;
+ Property *currentProperty() const;
+
+ QString qualifiedNameId() const;
+
+ QString textAt(const AST::SourceLocation &loc) const
+ { return _contents.mid(loc.offset, loc.length); }
+
+
+ QString textAt(const AST::SourceLocation &first,
+ const AST::SourceLocation &last) const
+ { return _contents.mid(first.offset, last.offset + last.length - first.offset); }
+
+ RewriteNumericLiterals rewriteNumericLiterals;
+
+ QString asString(AST::ExpressionNode *expr)
+ {
+ if (! expr)
+ return QString();
+
+ return rewriteNumericLiterals(textAt(expr->firstSourceLocation(), expr->lastSourceLocation()),
+ expr->firstSourceLocation().offset, expr);
+ }
+
+ QString asString(AST::Statement *stmt)
+ {
+ if (! stmt)
+ return QString();
+
+ QString s = rewriteNumericLiterals(textAt(stmt->firstSourceLocation(), stmt->lastSourceLocation()),
+ stmt->firstSourceLocation().offset, stmt);
+
+ s += QLatin1Char('\n');
+ return s;
+ }
+
+private:
+ QmlScriptParser *_parser;
+ StateStack _stateStack;
+ QStringList _scope;
+ QString _contents;
+
+ inline bool isSignalProperty(const QByteArray &propertyName) const {
+ return (propertyName.length() >= 3 && propertyName.startsWith("on") &&
+ ('A' <= propertyName.at(2) && 'Z' >= propertyName.at(2)));
+ }
+
+};
+
+ProcessAST::ProcessAST(QmlScriptParser *parser)
+ : _parser(parser)
+{
+}
+
+ProcessAST::~ProcessAST()
+{
+}
+
+void ProcessAST::operator()(const QString &code, AST::Node *node)
+{
+ _contents = code;
+ accept(node);
+}
+
+void ProcessAST::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+const ProcessAST::State ProcessAST::state() const
+{
+ if (_stateStack.isEmpty())
+ return State();
+
+ return _stateStack.back();
+}
+
+Object *ProcessAST::currentObject() const
+{
+ return state().object;
+}
+
+Property *ProcessAST::currentProperty() const
+{
+ return state().property;
+}
+
+QString ProcessAST::qualifiedNameId() const
+{
+ return _scope.join(QLatin1String("/"));
+}
+
+QString ProcessAST::asString(AST::UiQualifiedId *node) const
+{
+ QString s;
+
+ for (AST::UiQualifiedId *it = node; it; it = it->next) {
+ s.append(it->name->asString());
+
+ if (it->next)
+ s.append(QLatin1Char('.'));
+ }
+
+ return s;
+}
+
+Object *
+ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ int lastTypeDot = objectType.lastIndexOf(QLatin1Char('.'));
+ bool isType = !objectType.isEmpty() &&
+ (objectType.at(0).isUpper() ||
+ (lastTypeDot >= 0 && objectType.at(lastTypeDot+1).isUpper()));
+
+ int propertyCount = 0;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ this->location(propertyName));
+ }
+
+ if (!isType) {
+
+ if(propertyCount || !currentObject()) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected type name"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ return 0;
+ }
+
+ LocationSpan loc = ProcessAST::location(typeLocation, typeLocation);
+ if (propertyName)
+ loc = ProcessAST::location(propertyName);
+
+ _stateStack.pushProperty(objectType, loc);
+ accept(initializer);
+ _stateStack.pop();
+
+ return 0;
+
+ } else {
+ // Class
+
+ QString resolvableObjectType = objectType;
+ if (lastTypeDot >= 0)
+ resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/'));
+ const int typeId = _parser->findOrCreateTypeId(resolvableObjectType);
+
+ Object *obj = new Object;
+ obj->type = typeId;
+
+ // XXX this doesn't do anything (_scope never builds up)
+ _scope.append(resolvableObjectType);
+ obj->typeName = qualifiedNameId().toLatin1();
+ _scope.removeLast();
+
+ obj->location = location;
+
+ if (propertyCount) {
+
+ Property *prop = currentProperty();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ } else {
+
+ if (! _parser->tree()) {
+ _parser->setTree(obj);
+ } else {
+ const State state = _stateStack.top();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ if (state.property)
+ state.property->addValue(v);
+ else
+ state.object->getDefaultProperty()->addValue(v);
+ }
+ }
+
+ _stateStack.pushObject(obj);
+ accept(initializer);
+ _stateStack.pop();
+
+ return obj;
+ }
+}
+
+Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
+ AST::UiQualifiedId *objectTypeName,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ const QString objectType = asString(objectTypeName);
+ const AST::SourceLocation typeLocation = objectTypeName->identifierToken;
+
+ if (objectType == QLatin1String("Connection")) {
+
+ Object *obj = defineObjectBinding_helper(/*propertyName = */0, objectType, typeLocation, location);
+
+ _stateStack.pushObject(obj);
+
+ AST::UiObjectMemberList *it = initializer->members;
+ for (; it; it = it->next) {
+ AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(it->member);
+ if (! scriptBinding)
+ continue;
+
+ QString propertyName = asString(scriptBinding->qualifiedId);
+ if (propertyName == QLatin1String("script")) {
+ QString script;
+
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) {
+ script = getVariant(stmt->expression).asScript();
+ } else {
+ script = asString(scriptBinding->statement);
+ }
+
+ LocationSpan l = this->location(scriptBinding->statement->firstSourceLocation(),
+ scriptBinding->statement->lastSourceLocation());
+
+ _stateStack.pushProperty(QLatin1String("script"), l);
+ Value *value = new Value;
+ value->value = QmlParser::Variant(script);
+ value->location = l;
+ currentProperty()->addValue(value);
+ _stateStack.pop();
+ } else {
+ accept(it->member);
+ }
+ }
+
+ _stateStack.pop(); // object
+
+ return obj;
+ }
+
+ return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer);
+}
+
+LocationSpan ProcessAST::location(AST::UiQualifiedId *id)
+{
+ return location(id->identifierToken, id->identifierToken);
+}
+
+LocationSpan ProcessAST::location(AST::SourceLocation start, AST::SourceLocation end)
+{
+ LocationSpan rv;
+ rv.start.line = start.startLine;
+ rv.start.column = start.startColumn;
+ rv.end.line = end.startLine;
+ rv.end.column = end.startColumn + end.length - 1;
+ rv.range.offset = start.offset;
+ rv.range.length = end.offset + end.length - start.offset;
+ return rv;
+}
+
+// UiProgram: UiImportListOpt UiObjectMemberList ;
+bool ProcessAST::visit(AST::UiProgram *node)
+{
+ accept(node->imports);
+ accept(node->members->member);
+ return false;
+}
+
+// UiImport: T_IMPORT T_STRING_LITERAL ;
+bool ProcessAST::visit(AST::UiImport *node)
+{
+ QString fileName = node->fileName->asString();
+ _parser->addNamespacePath(fileName);
+
+ AST::SourceLocation startLoc = node->importToken;
+ AST::SourceLocation endLoc = node->semicolonToken;
+
+ QmlScriptParser::Import import;
+ import.location = location(startLoc, endLoc);
+ import.uri = fileName;
+
+ _parser->_imports << import;
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiPublicMember *node)
+{
+ if(node->type == AST::UiPublicMember::Signal) {
+ const QString name = node->name->asString();
+
+ Object::DynamicSignal signal;
+ signal.name = name.toUtf8();
+
+ _stateStack.top().object->dynamicSignals << signal;
+ } else {
+ const QString memberType = node->memberType->asString();
+ const QString name = node->name->asString();
+
+ const struct TypeNameToType {
+ const char *name;
+ Object::DynamicProperty::Type type;
+ } propTypeNameToTypes[] = {
+ { "int", Object::DynamicProperty::Int },
+ { "bool", Object::DynamicProperty::Bool },
+ { "double", Object::DynamicProperty::Real },
+ { "real", Object::DynamicProperty::Real },
+ { "string", Object::DynamicProperty::String },
+ { "color", Object::DynamicProperty::Color },
+ { "date", Object::DynamicProperty::Date },
+ { "var", Object::DynamicProperty::Variant },
+ { "variant", Object::DynamicProperty::Variant }
+ };
+ const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
+ sizeof(propTypeNameToTypes[0]);
+
+ bool typeFound = false;
+ Object::DynamicProperty::Type type;
+ for(int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
+ if(QLatin1String(propTypeNameToTypes[ii].name) == memberType) {
+ type = propTypeNameToTypes[ii].type;
+ typeFound = true;
+ }
+ }
+
+ if(!typeFound) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected property type"));
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ Object::DynamicProperty property;
+ property.isDefaultProperty = node->isDefaultMember;
+ property.type = type;
+ property.name = name.toUtf8();
+
+ if (node->expression) { // default value
+ property.defaultValue = new Property;
+ property.defaultValue->parent = _stateStack.top().object;
+ Value *value = new Value;
+ value->location = location(node->expression->firstSourceLocation(),
+ node->expression->lastSourceLocation());
+ value->value = getVariant(node->expression);
+ property.defaultValue->values << value;
+ }
+
+ _stateStack.top().object->dynamicProperties << property;
+ }
+
+ return true;
+}
+
+
+// UiObjectMember: UiQualifiedId UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectDefinition *node)
+{
+ LocationSpan l = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+
+ defineObjectBinding(/*propertyName = */ 0,
+ node->qualifiedTypeNameId,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectBinding *node)
+{
+ LocationSpan l = location(node->qualifiedTypeNameId->identifierToken,
+ node->initializer->rbraceToken);
+
+ defineObjectBinding(node->qualifiedId,
+ node->qualifiedTypeNameId,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+QmlParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr)
+{
+ if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
+ return QmlParser::Variant(lit->value->asString());
+ } else if (expr->kind == AST::Node::Kind_TrueLiteral) {
+ return QmlParser::Variant(true);
+ } else if (expr->kind == AST::Node::Kind_FalseLiteral) {
+ return QmlParser::Variant(false);
+ } else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) {
+ if (lit->suffix == AST::NumericLiteral::noSuffix)
+ return QmlParser::Variant(lit->value, asString(expr));
+ else
+ return QmlParser::Variant(asString(expr), expr);
+
+ } else {
+
+ if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
+ if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
+ return QmlParser::Variant(-lit->value, asString(expr));
+ }
+ }
+
+ return QmlParser::Variant(asString(expr), expr);
+ }
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON Statement ;
+bool ProcessAST::visit(AST::UiScriptBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ Property *prop = currentProperty();
+
+ QmlParser::Variant primitive;
+
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) {
+ primitive = getVariant(stmt->expression);
+ } else { // do binding
+ primitive = QmlParser::Variant(asString(node->statement),
+ node->statement);
+ }
+
+ Value *v = new Value;
+ v->value = primitive;
+ v->location = location(node->statement->firstSourceLocation(),
+ node->statement->lastSourceLocation());
+
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return true;
+}
+
+// UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiObjectMemberList T_RBRACKET ;
+bool ProcessAST::visit(AST::UiArrayBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ accept(node->members);
+
+ // For the DOM, store the position of the T_LBRACKET upto the T_RBRACKET as the range:
+ Property* prop = currentProperty();
+ prop->listValueRange.offset = node->lbracketToken.offset;
+ prop->listValueRange.length = node->rbracketToken.offset + node->rbracketToken.length - node->lbracketToken.offset;
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiSourceElement *node)
+{
+ QmlParser::Object *obj = currentObject();
+
+ bool isScript = (obj && obj->typeName == "Script");
+
+ if (!isScript) {
+
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+
+ if(funDecl->formals) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Slot declarations must be parameterless"));
+ error.setLine(funDecl->lparenToken.startLine);
+ error.setColumn(funDecl->lparenToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ QString body = textAt(funDecl->lbraceToken, funDecl->rbraceToken);
+ Object::DynamicSlot slot;
+ slot.name = funDecl->name->asString().toUtf8();
+ slot.body = body;
+ obj->dynamicSlots << slot;
+ } else {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","JavaScript declaration outside Script element"));
+ error.setLine(node->firstSourceLocation().startLine);
+ error.setColumn(node->firstSourceLocation().startColumn);
+ _parser->_errors << error;
+ }
+ return false;
+
+ } else {
+ QString source;
+
+ int line = 0;
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+ line = funDecl->functionToken.startLine;
+ source = asString(funDecl);
+ } else if (AST::VariableStatement *varStmt = AST::cast<AST::VariableStatement *>(node->sourceElement)) {
+ // ignore variable declarations
+ line = varStmt->declarationKindToken.startLine;
+ }
+
+ Value *value = new Value;
+ value->location = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+ value->value = QmlParser::Variant(source);
+
+ obj->getDefaultProperty()->addValue(value);
+ }
+
+ return false;
+}
+
+} // end of anonymous namespace
+
+
+QmlScriptParser::QmlScriptParser()
+: root(0), data(0)
+{
+
+}
+
+QmlScriptParser::~QmlScriptParser()
+{
+ clear();
+}
+
+class QmlScriptParserJsASTData
+{
+public:
+ QmlScriptParserJsASTData(const QString &filename)
+ : nodePool(filename, &engine) {}
+
+ Engine engine;
+ NodePool nodePool;
+};
+
+bool QmlScriptParser::parse(const QByteArray &qmldata, const QUrl &url)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::QmlParsing> pt;
+#endif
+ clear();
+
+ const QString fileName = url.toString();
+
+ QTextStream stream(qmldata, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+
+ data = new QmlScriptParserJsASTData(fileName);
+
+ Lexer lexer(&data->engine);
+ lexer.setCode(code, /*line = */ 1);
+
+ Parser parser(&data->engine);
+
+ if (! parser.parse() || !_errors.isEmpty()) {
+
+ // Extract errors from the parser
+ foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
+
+ if (m.isWarning())
+ continue;
+
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription(m.message);
+ error.setLine(m.loc.startLine);
+ error.setColumn(m.loc.startColumn);
+ _errors << error;
+
+ }
+ }
+
+ if (_errors.isEmpty()) {
+ ProcessAST process(this);
+ process(code, parser.ast());
+
+ // Set the url for process errors
+ for(int ii = 0; ii < _errors.count(); ++ii)
+ _errors[ii].setUrl(url);
+ }
+
+ return _errors.isEmpty();
+}
+
+QMap<QString,QString> QmlScriptParser::nameSpacePaths() const
+{
+ return _nameSpacePaths;
+}
+
+QStringList QmlScriptParser::types() const
+{
+ return _typeNames;
+}
+
+Object *QmlScriptParser::tree() const
+{
+ return root;
+}
+
+QList<QmlScriptParser::Import> QmlScriptParser::imports() const
+{
+ return _imports;
+}
+
+QList<QmlError> QmlScriptParser::errors() const
+{
+ return _errors;
+}
+
+void QmlScriptParser::clear()
+{
+ if (root) {
+ root->release();
+ root = 0;
+ }
+ _nameSpacePaths.clear();
+ _typeNames.clear();
+ _errors.clear();
+
+ if (data) {
+ delete data;
+ data = 0;
+ }
+}
+
+int QmlScriptParser::findOrCreateTypeId(const QString &name)
+{
+ int index = _typeNames.indexOf(name);
+
+ if (index == -1) {
+ index = _typeNames.size();
+ _typeNames.append(name);
+ }
+
+ return index;
+}
+
+void QmlScriptParser::setTree(Object *tree)
+{
+ Q_ASSERT(! root);
+
+ root = tree;
+}
+
+void QmlScriptParser::addNamespacePath(const QString &path)
+{
+ _nameSpacePaths.insertMulti(QString(), path);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
new file mode 100644
index 0000000..3993194
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QMLSCRIPTPARSER_P_H
+#define QMLSCRIPTPARSER_P_H
+
+#include <QtCore/QList>
+#include <QtCore/QUrl>
+#include <QtDeclarative/qmlerror.h>
+#include "qmlparser_p.h"
+
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QByteArray;
+
+class QmlScriptParserJsASTData;
+class QmlScriptParser
+{
+public:
+ class Import
+ {
+ public:
+ Import() {}
+
+ QString uri;
+ QmlParser::LocationSpan location;
+ };
+
+ QmlScriptParser();
+ ~QmlScriptParser();
+
+ bool parse(const QByteArray &data, const QUrl &url = QUrl());
+
+ QMap<QString,QString> nameSpacePaths() const;
+ QStringList types() const;
+
+ QmlParser::Object *tree() const;
+ QList<Import> imports() const;
+
+ void clear();
+
+ QList<QmlError> errors() const;
+
+// ### private:
+ int findOrCreateTypeId(const QString &name);
+ void setTree(QmlParser::Object *tree);
+
+ void setScriptFile(const QString &filename) {_scriptFile = filename; }
+ QString scriptFile() const { return _scriptFile; }
+
+ void addNamespacePath(const QString &path);
+
+// ### private:
+ QList<QmlError> _errors;
+
+ QMap<QString,QString> _nameSpacePaths;
+ QmlParser::Object *root;
+ QList<Import> _imports;
+ QStringList _typeNames;
+ QString _scriptFile;
+ QmlScriptParserJsASTData *data;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QMLSCRIPTPARSER_P_H
diff --git a/src/declarative/qml/qmlstringconverters.cpp b/src/declarative/qml/qmlstringconverters.cpp
new file mode 100644
index 0000000..c1f4b8c
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qcolor.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qvariant.h>
+#include "qmlstringconverters_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static uchar fromHex(const uchar c, const uchar c2)
+{
+ uchar rv = 0;
+ if (c >= '0' && c <= '9')
+ rv += (c - '0') * 16;
+ else if (c >= 'A' && c <= 'F')
+ rv += (c - 'A' + 10) * 16;
+ else if (c >= 'a' && c <= 'f')
+ rv += (c - 'a' + 10) * 16;
+
+ if (c2 >= '0' && c2 <= '9')
+ rv += (c2 - '0');
+ else if (c2 >= 'A' && c2 <= 'F')
+ rv += (c2 - 'A' + 10);
+ else if (c2 >= 'a' && c2 <= 'f')
+ rv += (c2 - 'a' + 10);
+
+ return rv;
+}
+
+static uchar fromHex(const QString &s, int idx)
+{
+ uchar c = s.at(idx).toAscii();
+ uchar c2 = s.at(idx + 1).toAscii();
+ return fromHex(c, c2);
+}
+
+QVariant QmlStringConverters::variantFromString(const QString &s)
+{
+ if (s.isEmpty())
+ return QVariant(s);
+ if (s.startsWith(QLatin1Char('\'')) && s.endsWith(QLatin1Char('\''))) {
+ QString data = s.mid(1, s.length() - 2);
+ return QVariant(data);
+ }
+ bool ok = false;
+ QRectF r = rectFFromString(s, &ok);
+ if (ok) return QVariant(r);
+ QColor c = colorFromString(s, &ok);
+ if (ok) return QVariant(c);
+ QPointF p = pointFFromString(s, &ok);
+ if (ok) return QVariant(p);
+ QSizeF sz = sizeFFromString(s, &ok);
+ if (ok) return QVariant(sz);
+ bool b = boolFromString(s, &ok);
+ if (ok) return QVariant(b);
+
+ return QVariant(s);
+}
+
+QColor QmlStringConverters::colorFromString(const QString &s, bool *ok)
+{
+ if (s.startsWith(QLatin1Char('#')) && s.length() == 9) {
+ uchar a = fromHex(s, 1);
+ uchar r = fromHex(s, 3);
+ uchar g = fromHex(s, 5);
+ uchar b = fromHex(s, 7);
+ if (ok) *ok = true;
+ return QColor(r, g, b, a);
+ } else {
+ QColor rv;
+ if (s.startsWith(QLatin1Char('#')) || QColor::colorNames().contains(s.toLower()))
+ rv = QColor(s);
+ if (ok) *ok = rv.isValid();
+ return rv;
+ }
+}
+
+//expects input of "x,y"
+QPointF QmlStringConverters::pointFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 1) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ bool xGood, yGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1).toDouble(&yGood);
+ if (!xGood || !yGood) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QPointF(xCoord, yCoord);
+}
+
+//expects input of "widthxheight"
+QSizeF QmlStringConverters::sizeFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ bool wGood, hGood;
+ int index = s.indexOf(QLatin1Char('x'));
+ qreal width = s.left(index).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QSizeF(width, height);
+}
+
+//expects input of "x,y,widthxheight" //### use space instead of second comma?
+QRectF QmlStringConverters::rectFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 2 || s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ bool xGood, yGood, wGood, hGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal x = s.left(index).toDouble(&xGood);
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ qreal y = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ index = s.indexOf(QLatin1Char('x'), index2+1);
+ qreal width = s.mid(index2+1, index-index2-1).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!xGood || !yGood || !wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QRectF(x, y, width, height);
+}
+
+bool QmlStringConverters::boolFromString(const QString &str, bool *ok)
+{
+ if (str.isEmpty() || str == QLatin1String("false") || str == QLatin1String("0")) {
+ if (ok)
+ *ok = true;
+ return false;
+ } else if (str == QLatin1String("true") || str == QLatin1String("1")) {
+ if (ok)
+ *ok = true;
+ return true;
+ }
+
+ if (ok)
+ *ok = false;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlstringconverters_p.h b/src/declarative/qml/qmlstringconverters_p.h
new file mode 100644
index 0000000..ed1f959
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTRINGCONVERTERS_P_H
+#define QMLSTRINGCONVERTERS_P_H
+
+#include <QtCore/qglobal.h>
+class QColor;
+class QPointF;
+class QSizeF;
+class QRectF;
+class QString;
+class QByteArray;
+
+QT_BEGIN_NAMESPACE
+
+// XXX - Bauhaus currently uses these methods which is why they're exported
+namespace QmlStringConverters
+{
+ QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &);
+ QColor Q_DECLARATIVE_EXPORT colorFromString(const QString &, bool *ok = 0);
+ QPointF Q_DECLARATIVE_EXPORT pointFFromString(const QString &, bool *ok = 0);
+ QSizeF Q_DECLARATIVE_EXPORT sizeFFromString(const QString &, bool *ok = 0);
+ QRectF Q_DECLARATIVE_EXPORT rectFFromString(const QString &, bool *ok = 0);
+ bool Q_DECLARATIVE_EXPORT boolFromString(const QString &, bool *ok = 0);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTRINGCONVERTERS_P_H
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
new file mode 100644
index 0000000..c85524f
--- /dev/null
+++ b/src/declarative/qml/qmlvme.cpp
@@ -0,0 +1,993 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvme_p.h"
+#include <qfxperf.h>
+#include <private/qmlboundsignal_p.h>
+#include <private/qmlstringconverters_p.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <qml.h>
+#include <private/qmlcustomparser_p.h>
+#include <qperformancelog.h>
+#include <QStack>
+#include <QWidget>
+#include <private/qmlcompiledcomponent_p.h>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlcomponent.h>
+#include <qmlbindablevalue.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcomponent_p.h>
+#include "private/qmlvmemetaobject_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <private/qmlbindablevalue_p.h>
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) {
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateCustomObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrSetId);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrSetDefault);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateComponent);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreMetaObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreReal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreInteger);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBool);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreString);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreColor);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDate);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDateTime);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreTime);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStorePoint);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSize);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreVariant);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSignal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQmlList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignalObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreCompiledBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreValueSource);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrBeginObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCompleteObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignObjectList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchAttached);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQmlList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPopFetchedObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPopQList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPushProperty);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreStackObject);
+ Q_DECLARE_PERFORMANCE_METRIC(Dummy);
+}
+
+Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") {
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateObject, "CreateObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateCustomObject, "CreateCustomObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrSetId, "SetId");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrSetDefault, "SetDefault");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateComponent, "CreateComponent");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreMetaObject, "StoreMetaObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreReal, "StoreReal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreInteger, "StoreInteger");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBool, "StoreBool");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreString, "StoreString");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreColor, "StoreColor");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDate, "StoreDate");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDateTime, "StoreDateTime");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreTime, "StoreTime");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStorePoint, "StorePoint(F)");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSize, "StoreSize(F)");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreVariant, "StoreVariant");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObject, "StoreObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSignal, "StoreSignal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQmlList, "StoreObjectQmlList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignalObject, "AssignSignalObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBinding, "StoreBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreCompiledBinding, "StoreCompiledBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreValueSource, "StoreValueSource");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrBeginObject, "BeginObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCompleteObject, "CompleteObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignObjectList, "AssignObjectList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchAttached, "FetchAttached");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQmlList, "FetchQmlList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQList, "FetchQList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchObject, "FetchObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPopFetchedObject, "PopFetchedObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPopQList, "PopQList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPushProperty, "PushProperty");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreStackObject, "StoreStackObject");
+ Q_DEFINE_PERFORMANCE_METRIC(Dummy, "Dummy");
+}
+
+static inline int qIndexOfProperty(QObject *o, const char *name)
+{
+ int idx = o->metaObject()->indexOfProperty(name);
+ return idx;
+}
+
+QmlVME::QmlVME()
+{
+}
+
+#define VME_EXCEPTION(desc) \
+ { \
+ QString str; \
+ QDebug d(&str); \
+ d << desc; \
+ str = str.trimmed(); \
+ QmlError error; \
+ error.setDescription(str); \
+ error.setLine(instr.line); \
+ error.setUrl(comp->url); \
+ vmeErrors << error; \
+ break; \
+ }
+
+struct ListInstance
+{
+ ListInstance() {}
+ ListInstance(const QVariant &l, int t)
+ : list(l), type(t), qmlListInterface(0) {}
+ ListInstance(QmlPrivate::ListInterface *q, int t)
+ : type(t), qmlListInterface(q) {}
+
+ QVariant list;
+ int type;
+ QmlPrivate::ListInterface *qmlListInterface;
+};
+
+QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, int count)
+{
+ // XXX - All instances of QmlContext::activeContext() here should be
+ // replaced with the use of ctxt. However, this cannot be done until
+ // behaviours stop modifying the active context and expecting the
+ // instantiation to notice. Instead, QmlParserStatus::beginClass() should
+ // be able to return a QmlContext that is used for expressions and
+ // sub-instances on that type.
+ Q_ASSERT(comp);
+ Q_ASSERT(ctxt);
+ const QList<QmlCompiledComponent::TypeReference> &types = comp->types;
+ const QList<QString> &primitives = comp->primitives;
+ const QList<QByteArray> &datas = comp->datas;
+ const QList<QMetaObject *> &synthesizedMetaObjects = comp->synthesizedMetaObjects;;
+ const QList<QmlCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
+ const QList<int> &intData = comp->intData;
+ const QList<float> &floatData = comp->floatData;
+
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::VMEExecution> cr;
+#endif
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bindValues;
+ QmlEnginePrivate::SimpleList<QmlParserStatus> parserStatus;
+
+ QStack<QObject *> stack;
+ QStack<ListInstance> qliststack;
+
+ QStack<QmlMetaProperty> pushedProperties;
+ QObject **savedObjects = 0;
+
+ vmeErrors.clear();
+
+ if (start == -1) start = 0;
+ if (count == -1) count = comp->bytecode.count();
+
+ for (int ii = start; !isError() && ii < (start + count); ++ii) {
+ QmlInstruction &instr = comp->bytecode[ii];
+
+ switch(instr.type) {
+ case QmlInstruction::Init:
+ {
+ if (instr.init.dataSize) {
+ savedObjects = new QObject*[instr.init.dataSize];
+ ::memset(savedObjects, 0,
+ sizeof(QObject *)*instr.init.dataSize);
+ }
+
+ if (instr.init.bindingsSize)
+ bindValues = QmlEnginePrivate::SimpleList<QmlBindableValue>(instr.init.bindingsSize);
+ if (instr.init.parserStatusSize)
+ parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
+ }
+ break;
+
+ case QmlInstruction::CreateObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCreateObject> cc;
+#endif
+ QObject *o = types.at(instr.create.type).createInstance(QmlContext::activeContext());
+ if (!o) {
+ if(types.at(instr.create.type).component)
+ vmeErrors << types.at(instr.create.type).component->errors();
+
+ VME_EXCEPTION("Unable to create object of type" << types.at(instr.create.type).className);
+ }
+
+ if (instr.create.data != -1) {
+ QmlCustomParser *customParser =
+ types.at(instr.create.type).type->customParser();
+ customParser->setCustomData(o, datas.at(instr.create.data));
+ }
+ if (!stack.isEmpty()) {
+ QObject *parent = stack.top();
+ o->setParent(parent);
+ }
+ stack.push(o);
+ }
+ break;
+
+ case QmlInstruction::SetId:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrSetId> cc;
+#endif
+ QObject *target = stack.top();
+ QmlContext *ctxt =
+ QmlContext::activeContext();
+ ctxt->setContextProperty(primitives.at(instr.setId.value), target);
+
+ if (instr.setId.save != -1)
+ savedObjects[instr.setId.save] = target;
+ }
+ break;
+
+
+ case QmlInstruction::SetDefault:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrSetDefault> cc;
+#endif
+ QObject *target = stack.top();
+ QmlContext::activeContext()->addDefaultObject(target);
+ }
+ break;
+
+ case QmlInstruction::CreateComponent:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCreateComponent> cc;
+#endif
+ QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top());
+ stack.push(qcomp);
+ ii += instr.createComponent.count;
+ }
+ break;
+
+ case QmlInstruction::StoreMetaObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreMetaObject> cc;
+#endif
+ QObject *target = stack.top();
+ new QmlVMEMetaObject(target, synthesizedMetaObjects.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, comp);
+ }
+ break;
+
+ case QmlInstruction::StoreVariant:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreVariant> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ // XXX - can be more efficient
+ QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value));
+ a[0] = (void *)&v;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreString:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreString> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&primitives.at(instr.storeString.value);
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreReal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreReal> cc;
+#endif
+ QObject *target = stack.top();
+ //### moc treats qreal properties as having type double
+ double r = static_cast<double>(instr.storeReal.value);
+ void *a[1];
+ a[0] = &r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeReal.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreBool:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreBool> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&instr.storeBool.value;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeBool.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInteger:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreInteger> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&instr.storeInteger.value;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeReal.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreColor:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreColor> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QColor c = QColor::fromRgba(instr.storeColor.value);
+ a[0] = (void *)&c;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeColor.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDate:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreDate> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QDate d = QDate::fromJulianDay(instr.storeDate.value);
+ a[0] = (void *)&d;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDate.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreTime:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreTime> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QTime t;
+ t.setHMS(intData.at(instr.storeTime.valueIndex),
+ intData.at(instr.storeTime.valueIndex+1),
+ intData.at(instr.storeTime.valueIndex+2),
+ intData.at(instr.storeTime.valueIndex+3));
+ a[0] = (void *)&t;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDateTime:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreDateTime> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QTime t;
+ t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
+ intData.at(instr.storeDateTime.valueIndex+2),
+ intData.at(instr.storeDateTime.valueIndex+3),
+ intData.at(instr.storeDateTime.valueIndex+4));
+ QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
+ a[0] = (void *)&dt;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDateTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePoint:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStorePoint> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePointF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStorePoint> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QPointF p(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSize:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSize> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSizeF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSize> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ a[0] = (void *)&s;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRect:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreRect> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3)).toRect();
+ a[0] = (void *)&r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRectF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreRect> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QRectF r(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3));
+ a[0] = (void *)&r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreObject> cc;
+#endif
+ QObject *assignObj = stack.pop();
+ QObject *target = stack.top();
+
+ void *a[1];
+ a[0] = (void *)&assignObj;
+
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+
+
+ case QmlInstruction::AssignCustomType:
+ {
+ QObject *target = stack.top();
+ void *a[1];
+ QmlCompiledComponent::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
+ const QString &primitive = primitives.at(data.index);
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(data.type);
+ QVariant v = (*converter)(primitive);
+
+ QMetaProperty prop =
+ target->metaObject()->property(instr.assignCustomType.propertyIndex);
+ if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
+ VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name());
+
+ a[0] = (void *)v.data();
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.assignCustomType.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::AssignSignalObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignSignalObject> cc;
+#endif
+ // XXX optimize
+
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+ int sigIdx = instr.assignSignalObject.signal;
+ const QByteArray &pr = datas.at(sigIdx);
+
+ QmlMetaProperty prop(target, QLatin1String(pr));
+ if (prop.type() & QmlMetaProperty::SignalProperty) {
+
+ QMetaMethod method = QmlMetaType::defaultMethod(assign);
+ if (method.signature() == 0)
+ VME_EXCEPTION("Cannot assign object type" << assign->metaObject()->className() << "with no default method");
+
+ if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
+ VME_EXCEPTION("Cannot connect mismatched signal/slot" << method.signature() << prop.method().signature());
+
+ QMetaObject::connect(target, prop.coreIndex(), assign, method.methodIndex());
+
+ } else {
+ VME_EXCEPTION("Cannot assign an object to signal property" << pr);
+ }
+
+
+ }
+ break;
+
+ case QmlInstruction::StoreSignal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSignal> cc;
+#endif
+ QObject *target = stack.top();
+ // XXX scope
+ QMetaMethod signal =
+ target->metaObject()->method(instr.storeSignal.signalIndex);
+
+ if (signal.parameterTypes().isEmpty()) {
+ (void *)new QmlBoundSignal(QmlContext::activeContext(), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
+ } else {
+ (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
+ }
+ }
+ break;
+
+ case QmlInstruction::BeginObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrBeginObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
+ parserStatus.append(status);
+ status->d = &parserStatus.values[parserStatus.count - 1];
+
+ status->classBegin();
+ }
+ break;
+
+ case QmlInstruction::CompleteObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCompleteObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.complete.castValue);
+ status->classComplete();
+ }
+ break;
+
+ case QmlInstruction::PushProperty:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPushProperty> cc;
+#endif
+ QObject *target = stack.top();
+ QmlMetaProperty mp(target, instr.pushProperty.property,
+ QmlMetaProperty::Object);
+ pushedProperties.push(mp);
+ }
+ break;
+
+ case QmlInstruction::StoreCompiledBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreCompiledBinding> cc;
+#endif
+ QObject *target = stack.top();
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp(target, instr.assignBinding.property,
+ (QmlMetaProperty::PropertyCategory)instr.assignBinding.category);
+
+ QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, 0);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
+ QFx_setParent_noEvent(bind, target);
+
+ bind->setTarget(mp);
+ bind->setSourceLocation(comp->url.toString(), instr.line);
+ }
+ break;
+
+ case QmlInstruction::StoreBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreBinding> cc;
+#endif
+ QObject *target = stack.top();
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp(target, instr.assignBinding.property,
+ (QmlMetaProperty::PropertyCategory)instr.assignBinding.category);
+
+ QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, false);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
+ QFx_setParent_noEvent(bind, target);
+
+ bind->setTarget(mp);
+ bind->setSourceLocation(comp->url.toString(), instr.line);
+ }
+ break;
+
+ case QmlInstruction::StoreValueSource:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreValueSource> cc;
+#endif
+ QObject *assign = stack.pop();
+ QmlPropertyValueSource *vs =
+ static_cast<QmlPropertyValueSource *>(assign);
+ QObject *target = stack.top();
+ vs->setParent(target);
+ vs->setTarget(QmlMetaProperty(target, instr.assignValueSource.property));
+ }
+ break;
+
+ case QmlInstruction::AssignObjectList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignObjectList> cc;
+#endif
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+ if (list.qmlListInterface) {
+ int type = list.type;
+
+ void *d = 0;
+ void *ptr = 0;
+ bool found = false;
+
+ if (QmlMetaType::isInterface(type)) {
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if (iid)
+ ptr = assign->qt_metacast(iid);
+ if (ptr) {
+ d = &ptr;
+ found = true;
+ }
+ } else {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *assignMo = assign->metaObject();
+ while(!found && assignMo) {
+ if (assignMo == mo)
+ found = true;
+ else
+ assignMo = assignMo->superClass();
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ d = (void *)&assign;
+ }
+
+
+ if (!found)
+ VME_EXCEPTION("Cannot assign object to list");
+
+ list.qmlListInterface->append(d);
+
+ } else {
+ int type = list.type;
+
+ if (QmlMetaType::isInterface(type)) {
+ void *ptr = 0;
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if (iid)
+ ptr = assign->qt_metacast(iid);
+ QVariant v(list.type, &ptr);
+ QmlMetaType::append(list.list, v);
+ } else {
+ QVariant v = QmlMetaType::fromObject(assign, list.type);
+ QmlMetaType::append(list.list, v);
+ }
+ }
+ }
+ break;
+
+ case QmlInstruction::StoreVariantObject:
+ {
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ QVariant v = QVariant::fromValue(assign);
+ void *a[1];
+ a[0] = (void *)&v;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInterface:
+ {
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ int coreIdx = instr.storeObject.propertyIndex;
+ QMetaProperty prop = target->metaObject()->property(coreIdx);
+ int t = prop.userType();
+ const char *iid = QmlMetaType::interfaceIId(t);
+ bool ok = false;
+ if (iid) {
+ void *ptr = assign->qt_metacast(iid);
+ if (ptr) {
+ void *a[1];
+ a[0] = &ptr;
+ QMetaObject::metacall(target,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ ok = true;
+ }
+ }
+
+ if (!ok)
+ VME_EXCEPTION("Cannot assign object to interface property");
+ }
+ break;
+
+ case QmlInstruction::FetchAttached:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchAttached> cc;
+#endif
+ QObject *target = stack.top();
+
+ QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
+
+ if (!qmlObject)
+ VME_EXCEPTION("Unable to create attached object");
+
+ stack.push(qmlObject);
+ }
+ break;
+
+ case QmlInstruction::FetchQmlList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchQmlList> cc;
+#endif
+ QObject *target = stack.top();
+
+ void *a[1];
+ // We know that QmlList<*> can be converted to
+ // QmlPrivate::ListInterface
+ QmlPrivate::ListInterface *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if (!list)
+ VME_EXCEPTION("Cannot assign to null list");
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
+ }
+ break;
+
+ case QmlInstruction::FetchQList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchQList> cc;
+#endif
+ QObject *target = stack.top();
+ QMetaProperty prop =
+ target->metaObject()->property(instr.fetch.property);
+ QVariant v = prop.read(target);
+ qliststack.push(ListInstance(v, QmlMetaType::listType(prop.userType())));
+ }
+ break;
+
+ case QmlInstruction::FetchObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchObject> cc;
+#endif
+ QObject *target = stack.top();
+
+ QObject *obj = 0;
+ if (instr.fetch.isObject) {
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = &obj;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+ } else {
+ void *a[1];
+ QVariant var;
+ a[0] = &var;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+ obj = QmlMetaType::toQObject(var);
+
+ }
+
+ if (!obj)
+ VME_EXCEPTION("Cannot set properties on" << target->metaObject()->property(instr.fetch.property).name() << "as it is null");
+
+ stack.push(obj);
+ }
+ break;
+
+ case QmlInstruction::PopQList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPopQList> cc;
+#endif
+ qliststack.pop();
+ }
+ break;
+
+ case QmlInstruction::PopFetchedObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPopFetchedObject> cc;
+#endif
+ stack.pop();
+ }
+ break;
+
+ case QmlInstruction::StoreStackObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreStackObject> cc;
+#endif
+
+ const QmlMetaProperty &prop =
+ pushedProperties.at(instr.assignStackObject.property);
+ QObject *obj = savedObjects[instr.assignStackObject.object];
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = (void *)&obj;
+ QMetaObject::metacall(prop.object(), QMetaObject::WriteProperty,
+ prop.coreIndex(), a);
+ }
+ break;
+
+ default:
+ qFatal("QmlCompiledComponent: Internal error - unknown instruction %d", instr.type);
+ break;
+ }
+ }
+
+ if (isError()) {
+ if (!stack.isEmpty()) {
+ delete stack.at(0);
+ }
+
+ QmlEnginePrivate::clear(bindValues);
+ QmlEnginePrivate::clear(parserStatus);
+ return 0;
+ }
+
+ QmlEnginePrivate *ep = ctxt->engine()->d_func();
+ if (bindValues.count)
+ ep->bindValues << bindValues;
+ if (parserStatus.count)
+ ep->parserStatus << parserStatus;
+
+ comp->dumpPost();
+
+ if (savedObjects)
+ delete [] savedObjects;
+
+ if (stack.isEmpty())
+ return 0;
+ else
+ return stack.top();
+ return 0;
+}
+
+bool QmlVME::isError() const
+{
+ return !vmeErrors.isEmpty();
+}
+
+QList<QmlError> QmlVME::errors() const
+{
+ return vmeErrors;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h
new file mode 100644
index 0000000..f2ed576
--- /dev/null
+++ b/src/declarative/qml/qmlvme_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVME_P_H
+#define QMLVME_P_H
+
+#include <QtCore/QString>
+#include <QtCore/QStack>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_NAMESPACE
+class QObject;
+class QmlInstruction;
+class QmlCompiledComponent;
+class QmlCompiledData;
+class QmlContext;
+
+class QmlVME
+{
+public:
+ QmlVME();
+
+ QObject *run(QmlContext *, QmlCompiledComponent *, int start = -1, int end = -1);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+private:
+ QList<QmlError> vmeErrors;
+};
+
+QT_END_NAMESPACE
+#endif // QMLVME_P_H
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
new file mode 100644
index 0000000..58708cf
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvmemetaobject_p.h"
+#include <qml.h>
+#include <private/qmlrefcount_p.h>
+#include <QColor>
+#include <QDate>
+#include <QtCore/qlist.h>
+#include <QtCore/qdebug.h>
+#include <qmlexpression.h>
+
+
+QT_BEGIN_NAMESPACE
+QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj,
+ const QMetaObject *other,
+ QList<QString> *strData,
+ int slotData,
+ QmlRefCount *rc)
+: object(obj), ref(rc), slotData(strData), slotDataIdx(slotData)
+{
+ if (ref)
+ ref->addref();
+
+ *static_cast<QMetaObject *>(this) = *other;
+ this->d.superdata = obj->metaObject();
+ QObjectPrivate::get(obj)->metaObject = this;
+
+ baseProp = propertyOffset();
+ baseSig = methodOffset();
+ data = new QVariant[propertyCount() - baseProp];
+ vTypes.resize(propertyCount() - baseProp);
+
+ // ### Optimize
+ for (int ii = baseProp; ii < propertyCount(); ++ii) {
+ QMetaProperty prop = property(ii);
+ if ((int)prop.type() != -1) {
+ data[ii - baseProp] = QVariant((QVariant::Type)prop.userType());
+ } else {
+ vTypes.setBit(ii - baseProp, true);
+ }
+ }
+
+ baseSlot = -1;
+ slotCount = 0;
+ for (int ii = baseSig; ii < methodCount(); ++ii) {
+ QMetaMethod m = method(ii);
+ if (m.methodType() == QMetaMethod::Slot) {
+ if (baseSlot == -1)
+ baseSlot = ii;
+ } else {
+ if (baseSlot != -1) {
+ slotCount = ii - baseSlot;
+ break;
+ }
+ }
+ }
+ if(baseSlot != -1 && !slotCount)
+ slotCount = methodCount() - baseSlot;
+}
+
+QmlVMEMetaObject::~QmlVMEMetaObject()
+{
+ if (ref)
+ ref->release();
+ delete [] data;
+}
+
+int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
+ if (id >= baseProp) {
+ int propId = id - baseProp;
+ bool needActivate = false;
+
+ if (vTypes.testBit(propId)) {
+ if (c == QMetaObject::ReadProperty) {
+ *reinterpret_cast<QVariant *>(a[0]) = data[propId];
+ } else if (c == QMetaObject::WriteProperty) {
+ needActivate =
+ (data[propId] != *reinterpret_cast<QVariant *>(a[0]));
+ data[propId] = *reinterpret_cast<QVariant *>(a[0]);
+ }
+ } else {
+ if (c == QMetaObject::ReadProperty) {
+ switch(data[propId].type()) {
+ case QVariant::Int:
+ *reinterpret_cast<int *>(a[0]) = data[propId].toInt();
+ break;
+ case QVariant::Bool:
+ *reinterpret_cast<bool *>(a[0]) = data[propId].toBool();
+ break;
+ case QVariant::Double:
+ *reinterpret_cast<double *>(a[0]) = data[propId].toDouble();
+ break;
+ case QVariant::String:
+ *reinterpret_cast<QString *>(a[0]) = data[propId].toString();
+ break;
+ case QVariant::Color:
+ *reinterpret_cast<QColor *>(a[0]) = data[propId].value<QColor>();
+ break;
+ case QVariant::Date:
+ *reinterpret_cast<QDate *>(a[0]) = data[propId].toDate();
+ break;
+ default:
+ qFatal("Unknown type");
+ break;
+ }
+ } else if (c == QMetaObject::WriteProperty) {
+
+ QVariant value = QVariant((QVariant::Type)data[propId].type(), a[0]);
+ needActivate = (data[propId] != value);
+ data[propId] = value;
+ }
+ }
+
+ if (c == QMetaObject::WriteProperty && needActivate) {
+ activate(object, baseSig + propId, 0);
+ }
+
+ return id;
+ }
+ } else if(c == QMetaObject::InvokeMetaMethod) {
+ if(id >= baseSlot && id < (baseSlot + slotCount)) {
+ int idx = id - baseSlot + slotDataIdx;
+ QmlContext *ctxt = qmlContext(object);
+ QmlExpression expr(ctxt, slotData->at(idx), object);
+ expr.setTrackChange(false);
+ expr.value();
+ return id;
+ }
+ }
+
+ return object->qt_metacall(c, id, a);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
new file mode 100644
index 0000000..6f1e31b
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVMEMETAOBJECT_P_H
+#define QMLVMEMETAOBJECT_P_H
+
+#include <QtDeclarative/qml.h>
+#include <QtCore/QMetaObject>
+#include <QtCore/QBitArray>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+class QmlRefCount;
+class QmlVMEMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlVMEMetaObject(QObject *, const QMetaObject *, QList<QString> *, int slotData, QmlRefCount * = 0);
+ ~QmlVMEMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QObject *object;
+ QmlRefCount *ref;
+ int baseProp;
+ int baseSig;
+ int baseSlot;
+ int slotCount;
+ QVariant *data;
+ QBitArray vTypes;
+ QList<QString> *slotData;
+ int slotDataIdx;
+};
+
+QT_END_NAMESPACE
+#endif // QMLVMEMETAOBJECT_P_H
diff --git a/src/declarative/qml/rewriter/rewriter.cpp b/src/declarative/qml/rewriter/rewriter.cpp
new file mode 100644
index 0000000..fce4fdf
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rewriter_p.h"
+#include "javascriptast_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace JavaScript;
+
+void Rewriter::replace(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset, loc.length, text); }
+
+void Rewriter::remove(const AST::SourceLocation &loc)
+{ return replace(loc.offset, loc.length, QString()); }
+
+void Rewriter::remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc)
+{ return replace(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, QString()); }
+
+void Rewriter::insertTextBefore(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset, 0, text); }
+
+void Rewriter::insertTextAfter(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset + loc.length, 0, text); }
+
+void Rewriter::replace(int offset, int length, const QString &text)
+{ textWriter.replace(offset, length, text); }
+
+void Rewriter::insertText(int offset, const QString &text)
+{ replace(offset, 0, text); }
+
+void Rewriter::removeText(int offset, int length)
+{ replace(offset, length, QString()); }
+
+QString Rewriter::textAt(const AST::SourceLocation &loc) const
+{ return _code.mid(loc.offset, loc.length); }
+
+QString Rewriter::textAt(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc) const
+{ return _code.mid(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset); }
+
+void Rewriter::accept(JavaScript::AST::Node *node)
+{ JavaScript::AST::Node::acceptChild(node, this); }
+
+void Rewriter::moveTextBefore(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc)
+{
+ textWriter.move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset);
+}
+
+void Rewriter::moveTextAfter(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc)
+{
+ textWriter.move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset + loc.length);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/rewriter/rewriter.pri b/src/declarative/qml/rewriter/rewriter.pri
new file mode 100644
index 0000000..de3c298
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter.pri
@@ -0,0 +1,9 @@
+
+INCLUDEPATH += $$PWD
+HEADERS += $$PWD/textwriter_p.h
+SOURCES += $$PWD/textwriter.cpp
+
+!no_ast_rewriter {
+ HEADERS += $$PWD/rewriter_p.h
+ SOURCES += $$PWD/rewriter.cpp
+}
diff --git a/src/declarative/qml/rewriter/rewriter_p.h b/src/declarative/qml/rewriter/rewriter_p.h
new file mode 100644
index 0000000..02b4ee4
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REWRITER_H
+#define REWRITER_H
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+#include "textwriter_p.h"
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+////////////////////////////////////////////////////////////////////////////////
+// Replacement
+////////////////////////////////////////////////////////////////////////////////
+class Replacement
+{
+ int _offset;
+ int _length;
+ QString _text;
+
+public:
+ Replacement(int offset = 0, int length = 0, const QString &text = QString())
+ : _offset(offset), _length(length), _text(text)
+ { }
+
+ bool isNull() const { return _offset == _length; }
+ operator bool() const { return ! isNull(); }
+
+ int offset() const { return _offset; }
+ int length() const { return _length; }
+ QString text() const { return _text; }
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Rewriter
+////////////////////////////////////////////////////////////////////////////////
+class Rewriter: public AST::Visitor
+{
+protected:
+ TextWriter textWriter;
+public:
+ //
+ // Token based API
+ //
+
+ /// Returns the text of the token at the given \a location.
+ QString textAt(const AST::SourceLocation &location) const;
+
+ QString textAt(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc) const;
+
+ /// Replace the token at \a loc with the given \a text.
+ void replace(const AST::SourceLocation &loc, const QString &text);
+
+ /// Remove the token at the given \a location.
+ void remove(const AST::SourceLocation &location);
+
+ /// Remove all tokens in the range [\a firstLoc, \a lastLoc].
+ void remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc);
+
+ /// Insert \a text before the token at the given \a location.
+ void insertTextBefore(const AST::SourceLocation &location, const QString &text);
+
+ /// Insert \a text after the token at the given \a location.
+ void insertTextAfter(const AST::SourceLocation &loc, const QString &text);
+
+ void moveTextBefore(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc);
+
+ void moveTextAfter(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc);
+
+ //
+ // low-level offset based API
+ //
+ void replace(int offset, int length, const QString &text);
+ void insertText(int offset, const QString &text);
+ void removeText(int offset, int length);
+
+ /// Visit the given \a node.
+ void accept(AST::Node *node);
+
+ /// Returns the original unchanged source code.
+ QString code() const { return _code; }
+
+ /// Returns the list of replacements.
+ QList<Replacement> replacementList() const { return _replacementList; }
+
+protected:
+ /// \internal
+ void setCode(const QString &code) { _code = code; }
+
+private:
+ QString _code;
+ QList<Replacement> _replacementList;
+};
+
+} // end of namespace JavaScript
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // REWRITER_H
diff --git a/src/declarative/qml/rewriter/textwriter.cpp b/src/declarative/qml/rewriter/textwriter.cpp
new file mode 100644
index 0000000..21122ff
--- /dev/null
+++ b/src/declarative/qml/rewriter/textwriter.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "textwriter_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace JavaScript;
+
+TextWriter::TextWriter()
+ :string(0), cursor(0)
+{
+}
+
+static bool overlaps(int posA, int lengthA, int posB, int lengthB) {
+ return (posA < posB + lengthB && posA + lengthA > posB + lengthB)
+ || (posA < posB && posA + lengthA > posB);
+}
+
+bool TextWriter::hasOverlap(int pos, int length)
+{
+ {
+ QListIterator<Replace> i(replaceList);
+ while (i.hasNext()) {
+ const Replace &cmd = i.next();
+ if (overlaps(pos, length, cmd.pos, cmd.length))
+ return true;
+ }
+ }
+ {
+ QListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ const Move &cmd = i.next();
+ if (overlaps(pos, length, cmd.pos, cmd.length))
+ return true;
+ }
+ return false;
+ }
+}
+
+bool TextWriter::hasMoveInto(int pos, int length)
+{
+ QListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ const Move &cmd = i.next();
+ if (cmd.to >= pos && cmd.to < pos + length)
+ return true;
+ }
+ return false;
+}
+
+void TextWriter::replace(int pos, int length, const QString &replacement)
+{
+ Q_ASSERT(!hasOverlap(pos, length));
+ Q_ASSERT(!hasMoveInto(pos, length));
+
+ Replace cmd;
+ cmd.pos = pos;
+ cmd.length = length;
+ cmd.replacement = replacement;
+ replaceList += cmd;
+}
+
+void TextWriter::move(int pos, int length, int to)
+{
+ Q_ASSERT(!hasOverlap(pos, length));
+
+ Move cmd;
+ cmd.pos = pos;
+ cmd.length = length;
+ cmd.to = to;
+ moveList += cmd;
+}
+
+void TextWriter::doReplace(const Replace &replace)
+{
+ int diff = replace.replacement.size() - replace.length;
+ {
+ QMutableListIterator<Replace> i(replaceList);
+ while (i.hasNext()) {
+ Replace &c = i.next();
+ if (replace.pos < c.pos)
+ c.pos += diff;
+ else if (replace.pos + replace.length < c.pos + c.length)
+ c.length += diff;
+ }
+ }
+ {
+ QMutableListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ Move &c = i.next();
+ if (replace.pos < c.pos)
+ c.pos += diff;
+ else if (replace.pos + replace.length < c.pos + c.length)
+ c.length += diff;
+
+ if (replace.pos < c.to)
+ c.to += diff;
+ }
+ }
+
+ if (string) {
+ string->replace(replace.pos, replace.length, replace.replacement);
+ } else if (cursor) {
+ cursor->setPosition(replace.pos);
+ cursor->setPosition(replace.pos + replace.length, QTextCursor::KeepAnchor);
+ cursor->insertText(replace.replacement);
+ }
+}
+
+void TextWriter::doMove(const Move &move)
+{
+ QString text;
+ if (string) {
+ text = string->mid(move.pos, move.length);
+ } else if (cursor) {
+ cursor->setPosition(move.pos);
+ cursor->setPosition(move.pos + move.length, QTextCursor::KeepAnchor);
+ text = cursor->selectedText();
+ }
+
+ Replace cut;
+ cut.pos = move.pos;
+ cut.length = move.length;
+ Replace paste;
+ paste.pos = move.to;
+ paste.length = 0;
+ paste.replacement = text;
+
+ replaceList.append(cut);
+ replaceList.append(paste);
+
+ Replace cmd;
+ while (!replaceList.isEmpty()) {
+ cmd = replaceList.first();
+ replaceList.removeFirst();
+ doReplace(cmd);
+ }
+}
+
+void TextWriter::write(QString *s)
+{
+ string = s;
+ write_helper();
+ string = 0;
+}
+
+void TextWriter::write(QTextCursor *textCursor)
+{
+ cursor = textCursor;
+ write_helper();
+ cursor = 0;
+}
+
+void TextWriter::write_helper()
+{
+ if (cursor)
+ cursor->beginEditBlock();
+ {
+ Replace cmd;
+ while (!replaceList.isEmpty()) {
+ cmd = replaceList.first();
+ replaceList.removeFirst();
+ doReplace(cmd);
+ }
+ }
+ {
+ Move cmd;
+ while (!moveList.isEmpty()) {
+ cmd = moveList.first();
+ moveList.removeFirst();
+ doMove(cmd);
+ }
+ }
+ if (cursor)
+ cursor->endEditBlock();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/rewriter/textwriter_p.h b/src/declarative/qml/rewriter/textwriter_p.h
new file mode 100644
index 0000000..57800bf
--- /dev/null
+++ b/src/declarative/qml/rewriter/textwriter_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTWRITER_H
+#define TEXTWRITER_H
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtGui/QTextCursor>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+class TextWriter
+{
+ QString *string;
+ QTextCursor *cursor;
+
+ struct Replace {
+ int pos;
+ int length;
+ QString replacement;
+ };
+
+ QList<Replace> replaceList;
+
+ struct Move {
+ int pos;
+ int length;
+ int to;
+ };
+
+ QList<Move> moveList;
+
+ bool hasOverlap(int pos, int length);
+ bool hasMoveInto(int pos, int length);
+
+ void doReplace(const Replace &replace);
+ void doMove(const Move &move);
+
+ void write_helper();
+
+public:
+ TextWriter();
+
+ void replace(int pos, int length, const QString &replacement);
+ void move(int pos, int length, int to);
+
+ void write(QString *s);
+ void write(QTextCursor *textCursor);
+
+};
+
+} // end of namespace JavaScript
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // TEXTWRITER_H
diff --git a/src/declarative/test/qfxtestengine.cpp b/src/declarative/test/qfxtestengine.cpp
new file mode 100644
index 0000000..0d7e5df
--- /dev/null
+++ b/src/declarative/test/qfxtestengine.cpp
@@ -0,0 +1,463 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QFile>
+#include <QmlComponent>
+#include <qmltimeline.h>
+#include "qfxtestengine.h"
+#include "qfxtestobjects.h"
+#include <QCryptographicHash>
+#include <QApplication>
+#include <QKeyEvent>
+#include <QSimpleCanvas>
+#include <QMouseEvent>
+#include <qmlengine.h>
+#include <private/qabstractanimation_p.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+#define MAX_MISMATCHED_FRAMES 5
+#define MAX_MISMATCHED_PIXELS 5
+
+class QFxTestEnginePrivate : public QAbstractAnimation
+{
+public:
+ QFxTestEnginePrivate(QFxTestEngine *p)
+ : q(p), canvas(0), testMode(QFxTestEngine::NoTest), fullFrame(true),
+ status(Working), exitOnFail(true), mismatchedFrames(0),
+ lastFrameMismatch(false) {}
+
+ QFxTestEngine *q;
+
+ QmlEngine engine;
+ QSimpleCanvas *canvas;
+ QFxTestEngine::TestMode testMode;
+ QString testDirectory;
+
+ TestLog testData;
+ TestLog playbackTestData;
+ bool fullFrame;
+ QList<QImage> fullFrames;
+
+ virtual void updateCurrentTime(int);
+
+ void recordFrameEvent(const QImage &img);
+ void recordFullFrameEvent(const QImage &img);
+ void recordKeyEvent(QKeyEvent *e);
+ void recordMouseEvent(QMouseEvent *e);
+ void testPass();
+ void save(const QString &filename, bool = true);
+
+ enum MessageType { Success, Fail };
+ void message(MessageType t, const char *);
+
+ enum Status { Working, Failed, Passed };
+ Status status;
+ bool exitOnFail;
+
+ QList<TestObject *> toPost;
+ QSet<QEvent *> postedEvents;
+
+ // OpenGL seems to give inconsistent rendering results. We allow a small
+ // tolerance to compensate - a maximum number of mismatched frames and only
+ // one mismatch in a row
+ int mismatchedFrames;
+ bool lastFrameMismatch;
+
+ bool compare(const QImage &img1, const QImage &img2);
+
+ virtual int duration() const { return -1; }
+
+ int elapsed() { return currentTime(); }
+};
+
+bool QFxTestEnginePrivate::compare(const QImage &img1, const QImage &img2)
+{
+ if (img1.size() != img2.size()) {
+ qWarning() << "Image size mismatch" << img1.size() << img2.size();
+ return false;
+ }
+
+ int errorCount = 0;
+ for (int yy = 0; yy < img1.height(); ++yy) {
+ for (int xx = 0; xx < img1.width(); ++xx) {
+ if (img1.pixel(xx, yy) != img2.pixel(xx, yy)) {
+ errorCount++;
+ if (errorCount > MAX_MISMATCHED_PIXELS) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+QFxTestEngine::QFxTestEngine(TestMode mode, const QString &dir,
+ QSimpleCanvas *canvas, QObject *parent)
+: QObject(parent), d(new QFxTestEnginePrivate(this))
+{
+ Q_ASSERT(canvas);
+
+ d->canvas = canvas;
+ d->start();
+
+ d->testDirectory = dir;
+ d->testMode = mode;
+ if (d->testMode == RecordTest) {
+ qWarning("QFxTestEngine: Record ON");
+ } else if (d->testMode == PlaybackTest) {
+
+ QString fileName(d->testDirectory + QLatin1String("/manifest.qml"));
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning() << "QFxTestEngine: Unable to open file" << fileName;
+ return;
+ }
+
+ QByteArray data = f.readAll();
+ QmlComponent c(&d->engine, data, QUrl(d->testDirectory + QLatin1String("/manifest.qml")));
+ QObject *o = c.create();
+ TestLog *log = qobject_cast<TestLog *>(o);
+ if (log) {
+ log->setParent(this);
+ d->playbackTestData.actions() = log->actions();
+ qWarning() << "QFxTestEngine: Playback ON," << d->playbackTestData.actions().count() << "actions";
+ } else {
+ delete o;
+ qWarning() << "QFxTestEngine: File" << fileName << "is corrupt.";
+ return;
+ }
+ }
+
+ if (d->testMode != NoTest) {
+ QUnifiedTimer::instance()->setConsistentTiming(true);
+ QObject::connect(canvas, SIGNAL(framePainted()),
+ this, SLOT(framePainted()));
+
+ canvas->installEventFilter(this);
+ for (int ii = 0; ii < d->playbackTestData.actions().count(); ++ii) {
+ TestObject *o = d->playbackTestData.actions().at(ii);
+ if (TestMouse *m = qobject_cast<TestMouse *>(o))
+ d->toPost << m;
+ else if (TestKey *k = qobject_cast<TestKey *>(o))
+ d->toPost << k;
+ }
+ }
+}
+
+QFxTestEngine::~QFxTestEngine()
+{
+ delete d; d = 0;
+}
+
+void QFxTestEngine::framePainted()
+{
+ QImage img = d->canvas->asImage();
+
+ if (d->fullFrame) {
+ d->fullFrame = false;
+ d->recordFullFrameEvent(img);
+ } else {
+ d->recordFrameEvent(img);
+ }
+}
+
+void QFxTestEnginePrivate::recordFullFrameEvent(const QImage &img)
+{
+ TestFullFrame *ff = new TestFullFrame(q);
+ ff->setTime(elapsed());
+ ff->setFrameId(fullFrames.count());
+
+ fullFrames << img;
+ testData.actions() << ff;
+
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestFullFrame *pf = qobject_cast<TestFullFrame *>(playbackTestData.next());
+ QString filename = testDirectory + QLatin1String("/image") + QString::number(pf->frameId()) + QLatin1String(".png");
+ QImage recImg(filename);
+ if (!pf || !compare(recImg, img) || pf->time() != elapsed()) {
+ qDebug() << pf << pf->time() << elapsed();
+ message(Fail, "FFrame mismatch");
+ } else {
+ message(Success, "FFrame OK");
+ }
+
+ testPass();
+ }
+}
+
+static QByteArray toHex(uchar c)
+{
+ QByteArray rv;
+ uint h = c / 16;
+ uint l = c % 16;
+ if (h >= 10)
+ rv.append(h - 10 + 'A');
+ else
+ rv.append(h + '0');
+ if (l >= 10)
+ rv.append(l - 10 + 'A');
+ else
+ rv.append(l + '0');
+ return rv;
+}
+
+void QFxTestEnginePrivate::recordFrameEvent(const QImage &img)
+{
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ hash.addData((const char *)img.bits(), img.bytesPerLine() * img.height());
+
+ QByteArray result = hash.result();
+ QByteArray hexResult;
+ for (int ii = 0; ii < result.count(); ++ii)
+ hexResult.append(toHex(result.at(ii)));
+
+ TestFrame *f = new TestFrame(q);
+ f->setTime(elapsed());
+
+ f->setHash(QLatin1String(hexResult));
+ testData.actions() << f;
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestObject *o = playbackTestData.next();
+ TestFrame *f = qobject_cast<TestFrame *>(o);
+ if (!f || f->time() != elapsed() ||
+ f->hash() != QLatin1String(hexResult)) {
+ mismatchedFrames++;
+ if (mismatchedFrames > MAX_MISMATCHED_FRAMES ||
+ lastFrameMismatch)
+ message(Fail, "Frame mismatch");
+ else
+ message(Success, "Frame mismatch - within tolerance");
+ lastFrameMismatch = true;
+ } else {
+ message(Success, "Frame OK");
+ lastFrameMismatch = false;
+ }
+
+ testPass();
+ }
+}
+
+void QFxTestEnginePrivate::updateCurrentTime(int)
+{
+ if (status != Working)
+ return;
+
+ while(!toPost.isEmpty()) {
+ int t = elapsed();
+ TestObject *o = toPost.first();
+ if (testMode == QFxTestEngine::RecordTest)
+ o->setTime(t);
+ else if (o->time() != t)
+ return;
+ toPost.takeFirst();
+ if (TestMouse *m = qobject_cast<TestMouse *>(o)) {
+ QMouseEvent e((QEvent::Type)m->type(), m->pos(), m->globalPos(), (Qt::MouseButton)m->button(), (Qt::MouseButtons)m->buttons(), (Qt::KeyboardModifiers)0);
+ postedEvents.insert(&e);
+ QApplication::sendEvent(canvas, &e);
+ } else if (TestKey *k = qobject_cast<TestKey *>(o)) {
+ QKeyEvent e((QEvent::Type)k->type(), k->key(), (Qt::KeyboardModifiers)k->modifiers(), k->text());
+ postedEvents.insert(&e);
+ QApplication::sendEvent(canvas, &e);
+ }
+ }
+}
+
+bool QFxTestEngine::eventFilter(QObject *, QEvent *event)
+{
+ if (d->status != QFxTestEnginePrivate::Working)
+ return false;
+
+ if (event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseButtonDblClick ||
+ event->type() == QEvent::MouseButtonRelease ||
+ event->type() == QEvent::MouseMove) {
+ if (d->testMode == RecordTest && d->postedEvents.contains(event)) {
+ d->postedEvents.remove(event);
+ } else {
+ d->recordMouseEvent(static_cast<QMouseEvent *>(event));
+ return d->testMode == RecordTest;
+ }
+ } else if (event->type() == QEvent::KeyPress ||
+ event->type() == QEvent::KeyRelease) {
+ QKeyEvent *key = static_cast<QKeyEvent *>(event);
+ if (key->key() < Qt::Key_F1 || key->key() > Qt::Key_F9) {
+
+ if (d->testMode == RecordTest && d->postedEvents.contains(event)) {
+ d->postedEvents.remove(event);
+ } else {
+ d->recordKeyEvent(key);
+ return d->testMode == RecordTest;
+ }
+
+ }
+ }
+
+ return false;
+}
+
+void QFxTestEnginePrivate::recordMouseEvent(QMouseEvent *e)
+{
+ TestMouse *m = new TestMouse(q);
+ m->setTime(elapsed());
+ m->setType(e->type());
+ m->setButton(e->button());
+ m->setButtons(e->buttons());
+ m->setGlobalPos(e->globalPos());
+ m->setPos(e->pos());
+ testData.actions() << m;
+
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestMouse *m = qobject_cast<TestMouse *>(playbackTestData.next());
+ if (!m || m->time() != elapsed() ||
+ m->type() != e->type() ||
+ m->button() != e->button() ||
+ m->buttons() != e->buttons() ||
+// m->globalPos() != e->globalPos() ||
+ m->pos() != e->pos()) {
+ if (m)
+ qWarning() << m->time() << elapsed();
+ message(Fail, "Mouse mismatch");
+ } else
+ message(Success, "Mouse OK");
+
+ testPass();
+ } else {
+ toPost << m;
+ }
+
+}
+
+void QFxTestEnginePrivate::recordKeyEvent(QKeyEvent *e)
+{
+ TestKey *k = new TestKey(q);
+ k->setTime(elapsed());
+ k->setType(e->type());
+ k->setModifiers(e->QInputEvent::modifiers());
+ k->setText(e->text());
+ k->setKey(e->key());
+ testData.actions() << k;
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestKey *f = qobject_cast<TestKey *>(playbackTestData.next());
+ if (!f || f->time() != elapsed() ||
+ f->type() != e->type() ||
+ f->modifiers() != e->QInputEvent::modifiers() ||
+ f->text() != e->text() ||
+ f->key() != e->key())
+ message(Fail, "Key mismatch");
+ else
+ message(Success, "Key OK");
+
+ testPass();
+ } else {
+ toPost << k;
+ }
+}
+
+void QFxTestEngine::captureFullFrame()
+{
+ d->fullFrame = true;
+}
+
+void QFxTestEnginePrivate::message(MessageType t, const char *message)
+{
+ if (exitOnFail)
+ qWarning("%s", message);
+ if (t == Fail) {
+ if (exitOnFail) {
+ save(QLatin1String("manifest-fail.qml"), false);
+ qFatal("Failed");
+ } else {
+ status = Failed;
+ }
+ }
+}
+
+void QFxTestEnginePrivate::save(const QString &filename, bool images)
+{
+ qWarning() << "QFxTestEngine: Writing test data";
+
+ QFile manifest(testDirectory + QLatin1String("/") + filename);
+ manifest.open(QIODevice::WriteOnly);
+ testData.save(&manifest);
+ manifest.close();
+
+ if (images) {
+ for (int ii = 0; ii < fullFrames.count(); ++ii)
+ fullFrames.at(ii).save(testDirectory + QLatin1String("/image") + QString::number(ii) + QLatin1String(".png"));
+ }
+}
+
+void QFxTestEngine::save()
+{
+ if (d->testMode != RecordTest)
+ return;
+
+ d->save(QLatin1String("manifest.qml"));
+}
+
+void QFxTestEnginePrivate::testPass()
+{
+ if (playbackTestData.atEnd()) {
+ qWarning("Test PASSED");
+ if (exitOnFail) {
+ save(QLatin1String("manifest-play.qml"));
+ exit(0);
+ } else {
+ status = Passed;
+ }
+ }
+}
+
+bool QFxTestEngine::runTest()
+{
+ d->exitOnFail = false;
+ while(d->status == QFxTestEnginePrivate::Working)
+ QApplication::processEvents();
+ d->exitOnFail = true;
+ qWarning() << d->status;
+ return d->status == QFxTestEnginePrivate::Passed;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestengine.h b/src/declarative/test/qfxtestengine.h
new file mode 100644
index 0000000..44a140f
--- /dev/null
+++ b/src/declarative/test/qfxtestengine.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTENGINE_H_
+#define _QFXTESTENGINE_H_
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QSimpleCanvas;
+class QFxTestEnginePrivate;
+class Q_DECLARATIVE_EXPORT QFxTestEngine : public QObject
+{
+Q_OBJECT
+public:
+ enum TestMode { NoTest, RecordTest, PlaybackTest };
+
+ QFxTestEngine(TestMode, const QString &,
+ QSimpleCanvas *canvas, QObject * = 0);
+ virtual ~QFxTestEngine();
+
+ void captureFullFrame();
+ void save();
+
+ bool runTest();
+
+protected:
+ virtual bool eventFilter(QObject *, QEvent *);
+
+private Q_SLOTS:
+ void framePainted();
+
+private:
+ QFxTestEnginePrivate *d;
+};
+
+#endif // _QFXTESTENGINE_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/qfxtestobjects.cpp b/src/declarative/test/qfxtestobjects.cpp
new file mode 100644
index 0000000..12fc7fb
--- /dev/null
+++ b/src/declarative/test/qfxtestobjects.cpp
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qfxtestobjects.h"
+#include <qml.h>
+#include <QDebug>
+#include <QTextStream>
+
+
+QT_BEGIN_NAMESPACE
+QML_DECLARE_TYPE(TestObject)
+QML_DEFINE_TYPE(TestObject,TestObject)
+QML_DECLARE_TYPE(TestFrame)
+QML_DEFINE_TYPE(TestFrame,TestFrame)
+QML_DECLARE_TYPE(TestFullFrame)
+QML_DEFINE_TYPE(TestFullFrame,TestFullFrame)
+QML_DECLARE_TYPE(TestMouse)
+QML_DEFINE_TYPE(TestMouse,TestMouse)
+QML_DECLARE_TYPE(TestKey)
+QML_DEFINE_TYPE(TestKey,TestKey)
+QML_DECLARE_TYPE(TestLog)
+QML_DEFINE_TYPE(TestLog,TestLog)
+
+static QString padding(int pad)
+{
+ QString p;
+ while (pad--)
+ p += QLatin1Char(' ');
+ return p;
+}
+
+TestObject::TestObject(QObject *parent)
+: QObject(parent), _time(-1)
+{
+}
+
+int TestObject::time() const
+{
+ return _time;
+}
+
+void TestObject::setTime(int t)
+{
+ if (t == _time)
+ return;
+ _time = t;
+ emit dataChanged();
+}
+
+void TestObject::save(QTextStream &device, int pad)
+{
+ device << padding(pad) << QLatin1String("TestObject {") << endl;
+ device << padding(pad) << QLatin1String("time: ") << QString::number(time()) << endl;
+ device << padding(pad) << QLatin1String("}") << endl;
+}
+
+
+TestFrame::TestFrame(QObject *parent)
+: TestObject(parent)
+{
+}
+
+QString TestFrame::hash() const
+{
+ return _hash;
+}
+
+void TestFrame::setHash(const QString &h)
+{
+ if (_hash == h)
+ return;
+ _hash = h;
+ emit frameChanged();
+}
+
+void TestFrame::save(QTextStream &device, int pad)
+{
+ device << padding(pad) << QLatin1String("TestFrame {") << endl;
+ device << padding(pad+4) << QLatin1String("time: ") << QLatin1String(QByteArray::number(time())) << endl;
+ device << padding(pad+4)<< QLatin1String("hash: '") << hash() << QLatin1String("'") << endl;
+ device << padding(pad) << QLatin1Char('}') << endl;
+}
+
+TestFullFrame::TestFullFrame(QObject *parent)
+: TestObject(parent), _frameId(-1)
+{
+}
+
+int TestFullFrame::frameId() const
+{
+ return _frameId;
+}
+
+void TestFullFrame::setFrameId(int id)
+{
+ if (id == _frameId)
+ return;
+ _frameId = id;
+ emit frameChanged();
+}
+
+void TestFullFrame::save(QTextStream &device, int pad)
+{
+ device << padding(pad) << QLatin1String("TestFullFrame {") << endl;
+ device << padding(pad+4) << QLatin1String("time: ") << QLatin1String(QByteArray::number(time())) << endl;
+ device << padding(pad+4) << QLatin1String("frameId: ") << QLatin1String(QByteArray::number(frameId())) << endl;
+ device << padding(pad) << QLatin1String("}") << endl;
+}
+
+TestMouse::TestMouse(QObject *parent)
+: TestObject(parent), _type(-1), _button(-1), _buttons(-1)
+{
+}
+
+int TestMouse::type() const
+{
+ return _type;
+}
+
+void TestMouse::setType(int t)
+{
+ if (_type == t)
+ return;
+ _type = t;
+ emit mouseChanged();
+}
+
+int TestMouse::button() const
+{
+ return _button;
+}
+
+void TestMouse::setButton(int b)
+{
+ if (b == _button)
+ return;
+ _button = b;
+ emit mouseChanged();
+}
+
+int TestMouse::buttons() const
+{
+ return _buttons;
+}
+
+void TestMouse::setButtons(int buttons)
+{
+ if (_buttons == buttons)
+ return;
+ _buttons = buttons;
+ emit mouseChanged();
+}
+
+QPoint TestMouse::globalPos() const
+{
+ return _globalPos;
+}
+
+void TestMouse::setGlobalPos(const QPoint &g)
+{
+ if (_globalPos == g)
+ return;
+ _globalPos = g;
+ emit mouseChanged();
+}
+
+QPoint TestMouse::pos() const
+{
+ return _pos;
+}
+
+void TestMouse::setPos(const QPoint &p)
+{
+ if (p == _pos)
+ return;
+ _pos = p;
+ emit mouseChanged();
+}
+
+void TestMouse::save(QTextStream &device, int pad)
+{
+ device << padding(pad) << QLatin1String("TestMouse {") << endl;
+ device << padding(pad+4) << QLatin1String("time: ") << QString::number(time()) << endl;
+ device << padding(pad+4) << QLatin1String("type: ") << QString::number(type()) << endl;
+ device << padding(pad+4) << QLatin1String("button: ") << QString::number(button()) << endl;
+ device << padding(pad+4) << QLatin1String("buttons: ") << QString::number(buttons()) << endl;
+ device << padding(pad+4) << QLatin1String("globalPos: '") << QString::number(globalPos().x()) + QLatin1String(",") + QString::number(globalPos().y()) << QLatin1String("'") << endl;
+ device << padding(pad+4) << QLatin1String("pos: '") << QString::number(pos().x()) + QLatin1String(",") + QString::number(pos().y()) << QLatin1String("'") << endl;
+ device << padding(pad) << QLatin1String("}") << endl;
+}
+
+TestKey::TestKey(QObject *parent)
+: TestObject(parent), _type(-1), _modifiers(-1), _key(-1)
+{
+}
+
+int TestKey::type() const
+{
+ return _type;
+}
+
+void TestKey::setType(int t)
+{
+ if (t == _type)
+ return;
+ _type = t;
+ emit keyChanged();
+}
+
+int TestKey::modifiers() const
+{
+ return _modifiers;
+}
+
+void TestKey::setModifiers(int m)
+{
+ if (m == _modifiers)
+ return;
+ _modifiers = m;
+ emit keyChanged();
+}
+
+QString TestKey::text() const
+{
+ return _text;
+}
+
+void TestKey::setText(const QString &t)
+{
+ if (_text == t)
+ return;
+ _text = t;
+ emit keyChanged();
+}
+
+int TestKey::key() const
+{
+ return _key;
+}
+
+void TestKey::setKey(int k)
+{
+ if (_key == k)
+ return;
+ _key = k;
+ emit keyChanged();
+}
+
+void TestKey::save(QTextStream &device, int pad)
+{
+ device << padding(pad) << QLatin1String("TestKey {") << endl;
+ device << padding(pad+4) << QLatin1String("time: ") << QString::number(time()) << endl;
+ device << padding(pad+4) << QLatin1String("type: ") << QString::number(type()) << endl;
+ device << padding(pad+4) << QLatin1String("modifiers: ") << QString::number(modifiers()) << endl;
+ device << padding(pad+4) << QLatin1String("key: ") << QString::number(key()) << endl;
+ if (key() != Qt::Key_Escape)
+ device << padding(pad+4) << QLatin1String("text: '") << text() << QLatin1String("'")<< endl;
+ device << padding(pad) << QLatin1String("}") << endl;
+}
+
+TestLog::TestLog(QObject *parent)
+: QObject(parent), _current(0)
+{
+}
+
+QList<TestObject *> *TestLog::qmlActions()
+{
+ return &_actions;
+}
+
+QList<TestObject *> &TestLog::actions()
+{
+ return _actions;
+}
+
+bool lessThan(TestObject *lhs, TestObject *rhs)
+{
+ return lhs->time() < rhs->time();
+}
+
+void TestLog::save(QIODevice *device)
+{
+ // Order correctly
+ qStableSort(_actions.begin(), _actions.end(), lessThan);
+
+ QTextStream writer(device);
+ writer << QLatin1String("TestLog {") << endl;
+ for (int ii = 0; ii < _actions.count(); ++ii)
+ _actions.at(ii)->save(writer, 4);
+ writer << QLatin1String("}") << endl;
+}
+
+TestObject *TestLog::next()
+{
+ if (atEnd())
+ return 0;
+ TestObject *rv = _actions.at(_current);
+ _current++;
+ return rv;
+}
+
+bool TestLog::atEnd() const
+{
+ if (_current >= _actions.count())
+ return true;
+ else
+ return false;
+}
+
+int TestLog::current() const
+{
+ return _current;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestobjects.h b/src/declarative/test/qfxtestobjects.h
new file mode 100644
index 0000000..80fcfe7
--- /dev/null
+++ b/src/declarative/test/qfxtestobjects.h
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTOBJECTS_H_
+#define _QFXTESTOBJECTS_H_
+
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+#include <QtCore/QList>
+#include <QtCore/QTextStream>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QIODevice;
+class TestObject : public QObject
+{
+Q_OBJECT
+public:
+ TestObject(QObject * = 0);
+
+ Q_PROPERTY(int time READ time WRITE setTime NOTIFY dataChanged)
+ int time() const;
+ void setTime(int);
+
+ virtual void save(QTextStream &, int pad);
+Q_SIGNALS:
+ void dataChanged();
+
+private:
+ int _time;
+};
+
+class TestFrame : public TestObject
+{
+Q_OBJECT
+public:
+ TestFrame(QObject * = 0);
+
+ Q_PROPERTY(QString hash READ hash WRITE setHash NOTIFY frameChanged)
+ QString hash() const;
+ void setHash(const QString &);
+
+ virtual void save(QTextStream &, int pad);
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ QString _hash;
+};
+
+class TestFullFrame : public TestObject
+{
+Q_OBJECT
+public:
+ TestFullFrame(QObject * = 0);
+
+ Q_PROPERTY(int frameId READ frameId WRITE setFrameId NOTIFY frameChanged)
+ int frameId() const;
+ void setFrameId(int);
+
+ virtual void save(QTextStream &, int pad);
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ int _frameId;
+};
+
+class TestMouse : public TestObject
+{
+Q_OBJECT
+public:
+ TestMouse(QObject * = 0);
+
+ Q_PROPERTY(int type READ type WRITE setType NOTIFY mouseChanged)
+ int type() const;
+ void setType(int);
+
+ Q_PROPERTY(int button READ button WRITE setButton NOTIFY mouseChanged)
+ int button() const;
+ void setButton(int);
+
+ Q_PROPERTY(int buttons READ buttons WRITE setButtons NOTIFY mouseChanged)
+ int buttons() const;
+ void setButtons(int);
+
+ Q_PROPERTY(QPoint globalPos READ globalPos WRITE setGlobalPos NOTIFY mouseChanged)
+ QPoint globalPos() const;
+ void setGlobalPos(const QPoint &);
+
+ Q_PROPERTY(QPoint pos READ pos WRITE setPos NOTIFY mouseChanged)
+ QPoint pos() const;
+ void setPos(const QPoint &);
+
+ virtual void save(QTextStream &, int pad);
+
+Q_SIGNALS:
+ void mouseChanged();
+
+private:
+ int _type;
+ int _button;
+ int _buttons;
+ QPoint _globalPos;
+ QPoint _pos;
+};
+
+class TestKey : public TestObject
+{
+Q_OBJECT
+public:
+ TestKey(QObject * = 0);
+
+ Q_PROPERTY(int type READ type WRITE setType NOTIFY keyChanged)
+ int type() const;
+ void setType(int);
+
+ Q_PROPERTY(int modifiers READ modifiers WRITE setModifiers NOTIFY keyChanged)
+ int modifiers() const;
+ void setModifiers(int);
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY keyChanged)
+ QString text() const;
+ void setText(const QString &);
+
+ Q_PROPERTY(int key READ key WRITE setKey NOTIFY keyChanged)
+ int key() const;
+ void setKey(int);
+
+ virtual void save(QTextStream &, int pad);
+
+Q_SIGNALS:
+ void keyChanged();
+
+private:
+ int _type;
+ int _modifiers;
+ int _key;
+ QString _text;
+};
+
+class TestLog : public QObject
+{
+Q_OBJECT
+public:
+ TestLog(QObject * = 0);
+
+ Q_CLASSINFO("DefaultProperty", "actions")
+ Q_PROPERTY(QList<TestObject *> *actions READ qmlActions)
+ QList<TestObject *> *qmlActions();
+
+ QList<TestObject *> &actions();
+
+ int current() const;
+ void save(QIODevice *);
+
+ TestObject *next();
+ bool atEnd() const;
+
+private:
+ int _current;
+ QList<TestObject *> _actions;
+};
+
+#endif // _QFXTESTOBJECTS_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/qfxtestview.cpp b/src/declarative/test/qfxtestview.cpp
new file mode 100644
index 0000000..0bd5a6b
--- /dev/null
+++ b/src/declarative/test/qfxtestview.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxtestview.h"
+#include <QFile>
+#include <QmlComponent>
+#include <QFileInfo>
+#include <QFxItem>
+#include <QmlContext>
+#include <QFxTestEngine>
+
+
+QT_BEGIN_NAMESPACE
+QFxTestView::QFxTestView(const QString &filename, const QString &testdir)
+: testEngine(0)
+{
+ QObject::connect(this, SIGNAL(sceneResized(QSize)),
+ this, SLOT(setSceneSize(QSize)));
+
+ testEngine = new QFxTestEngine(QFxTestEngine::PlaybackTest, testdir, this, this);
+
+ qWarning() << "Testing:" << filename;
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = QString::fromUtf8(file.readAll());
+ setQml(qml, filename);
+
+ execute();
+}
+
+void QFxTestView::setSceneSize(QSize s)
+{
+ if (s.isNull())
+ qWarning() << "Scene size is invalid";
+ setFixedSize(s);
+}
+
+bool QFxTestView::runTest()
+{
+ show();
+ return testEngine->runTest();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestview.h b/src/declarative/test/qfxtestview.h
new file mode 100644
index 0000000..a8f78bf
--- /dev/null
+++ b/src/declarative/test/qfxtestview.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTVIEW_H_
+#define _QFXTESTVIEW_H_
+
+#include <QtDeclarative/QFxView>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxTestEngine;
+class Q_DECLARATIVE_EXPORT QFxTestView : public QFxView
+{
+Q_OBJECT
+public:
+ QFxTestView(const QString &filename, const QString &testdir);
+
+ bool runTest();
+
+private Q_SLOTS:
+ void setSceneSize(QSize);
+
+private:
+ QFxTestEngine *testEngine;
+};
+
+#endif // _QFXTESTVIEW_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/test.pri b/src/declarative/test/test.pri
new file mode 100644
index 0000000..eacd00f
--- /dev/null
+++ b/src/declarative/test/test.pri
@@ -0,0 +1,9 @@
+SOURCES += \
+ test/qfxtestengine.cpp \
+ test/qfxtestobjects.cpp \
+ test/qfxtestview.cpp
+
+HEADERS += \
+ test/qfxtestengine.h \
+ test/qfxtestobjects.h \
+ test/qfxtestview.h
diff --git a/src/declarative/timeline/qmltimeline.cpp b/src/declarative/timeline/qmltimeline.cpp
new file mode 100644
index 0000000..dcc8745
--- /dev/null
+++ b/src/declarative/timeline/qmltimeline.cpp
@@ -0,0 +1,940 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltimeline.h"
+#include <QDebug>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+#include <QEvent>
+#include <QCoreApplication>
+#include <QEasingCurve>
+#include <QTime>
+
+QT_BEGIN_NAMESPACE
+
+struct Update {
+ Update(QmlTimeLineValue *_g, qreal _v)
+ : g(_g), v(_v) {}
+ Update(const QmlTimeLineEvent &_e)
+ : g(0), v(0), e(_e) {}
+
+ QmlTimeLineValue *g;
+ qreal v;
+ QmlTimeLineEvent e;
+};
+
+struct QmlTimeLinePrivate
+{
+ QmlTimeLinePrivate(QmlTimeLine *);
+
+ struct Op {
+ enum Type {
+ Pause,
+ Set,
+ Move,
+ MoveBy,
+ Accel,
+ AccelDistance,
+ Execute
+ };
+ Op() {}
+ Op(Type t, int l, qreal v, qreal v2, int o,
+ const QmlTimeLineEvent &ev = QmlTimeLineEvent(), const QEasingCurve &es = QEasingCurve())
+ : type(t), length(l), value(v), value2(v2), order(o), event(ev),
+ easing(es) {}
+ Op(const Op &o)
+ : type(o.type), length(o.length), value(o.value), value2(o.value2),
+ order(o.order), event(o.event), easing(o.easing) {}
+ Op &operator=(const Op &o) {
+ type = o.type; length = o.length; value = o.value;
+ value2 = o.value2; order = o.order; event = o.event;
+ easing = o.easing;
+ return *this;
+ }
+
+ Type type;
+ int length;
+ qreal value;
+ qreal value2;
+
+ int order;
+ QmlTimeLineEvent event;
+ QEasingCurve easing;
+ };
+ struct TimeLine
+ {
+ TimeLine() : length(0), consumedOpLength(0), base(0.) {}
+ QList<Op> ops;
+ int length;
+ int consumedOpLength;
+ qreal base;
+ };
+
+ int length;
+ int syncPoint;
+ typedef QHash<QmlTimeLineObject *, TimeLine> Ops;
+ Ops ops;
+ QmlTimeLine *q;
+
+ void add(QmlTimeLineObject &, const Op &);
+ qreal value(const Op &op, int time, qreal base, bool *) const;
+
+ int advance(int);
+
+ bool clockRunning;
+ int prevTime;
+
+ int order;
+
+ QmlTimeLine::SyncMode syncMode;
+ int syncAdj;
+ QList<QPair<int, Update> > *updateQueue;
+};
+
+QmlTimeLinePrivate::QmlTimeLinePrivate(QmlTimeLine *parent)
+: length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(QmlTimeLine::LocalSync), syncAdj(0), updateQueue(0)
+{
+}
+
+void QmlTimeLinePrivate::add(QmlTimeLineObject &g, const Op &o)
+{
+ if (g._t && g._t != q) {
+ qWarning() << "QmlTimeLine: Cannot modify a QmlTimeLineValue owned by"
+ << "another timeline.";
+ return;
+ }
+ g._t = q;
+
+ Ops::Iterator iter = ops.find(&g);
+ if (iter == ops.end()) {
+ iter = ops.insert(&g, TimeLine());
+ if (syncPoint > 0)
+ q->pause(g, syncPoint);
+ }
+ if (!iter->ops.isEmpty() &&
+ o.type == Op::Pause &&
+ iter->ops.last().type == Op::Pause) {
+ iter->ops.last().length += o.length;
+ iter->length += o.length;
+ } else {
+ iter->ops.append(o);
+ iter->length += o.length;
+ }
+
+ if (iter->length > length)
+ length = iter->length;
+
+ if (!clockRunning) {
+ q->stop();
+ prevTime = 0;
+ clockRunning = true;
+
+ if (syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ q->start();
+/* q->tick(0);
+ if (syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ */
+ }
+}
+
+qreal QmlTimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
+{
+ Q_ASSERT(time >= 0);
+ Q_ASSERT(time <= op.length);
+ *changed = true;
+
+ switch(op.type) {
+ case Op::Pause:
+ *changed = false;
+ return base;
+ case Op::Set:
+ return op.value;
+ case Op::Move:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return op.value;
+ } else {
+ qreal delta = op.value - base;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::MoveBy:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value;
+ } else {
+ qreal delta = op.value;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::Accel:
+ if (time == 0) {
+ return base;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal delta = op.value * t + 0.5f * op.value2 * t * t;
+ return base + delta;
+ }
+ case Op::AccelDistance:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value2;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
+ qreal delta = op.value * t + 0.5f * accel * t * t;
+ return base + delta;
+
+ }
+ case Op::Execute:
+ op.event.execute();
+ *changed = false;
+ return -1;
+ }
+
+ return base;
+}
+
+/*!
+ \internal
+ \class QmlTimeLine
+ \ingroup group_animation
+ \brief The QmlTimeLine class provides a timeline for controlling animations.
+
+ QmlTimeLine is similar to QTimeLine except:
+ \list
+ \i It updates QmlTimeLineValue instances directly, rather than maintaining a single
+ current value.
+
+ For example, the following animates a simple value over 200 milliseconds:
+ \code
+ QmlTimeLineValue v(<starting value>);
+ QmlTimeLine tl;
+ tl.move(v, 100., 200);
+ tl.start()
+ \endcode
+
+ If your program needs to know when values are changed, it can either
+ connect to the QmlTimeLine's updated() signal, or inherit from QmlTimeLineValue
+ and reimplement the QmlTimeLineValue::setValue() method.
+
+ \i Supports multiple QmlTimeLineValue, arbitrary start and end values and allows
+ animations to be strung together for more complex effects.
+
+ For example, the following animation moves the x and y coordinates of
+ an object from wherever they are to the position (100, 100) in 50
+ milliseconds and then further animates them to (100, 200) in 50
+ milliseconds:
+
+ \code
+ QmlTimeLineValue x(<starting value>);
+ QmlTimeLineValue y(<starting value>);
+
+ QmlTimeLine tl;
+ tl.start();
+
+ tl.move(x, 100., 50);
+ tl.move(y, 100., 50);
+ tl.move(y, 200., 50);
+ \endcode
+
+ \i All QmlTimeLine instances share a single, synchronized clock.
+
+ Actions scheduled within the same event loop tick are scheduled
+ synchronously against each other, regardless of the wall time between the
+ scheduling. Synchronized scheduling applies both to within the same
+ QmlTimeLine and across separate QmlTimeLine's within the same process.
+
+ \endlist
+
+ Currently easing functions are not supported.
+*/
+
+
+/*!
+ Construct a new QmlTimeLine with the specified \a parent.
+*/
+QmlTimeLine::QmlTimeLine(QObject *parent)
+: QAbstractAnimation(parent)
+{
+ d = new QmlTimeLinePrivate(this);
+}
+
+/*!
+ Destroys the time line. Any inprogress animations are canceled, but not
+ completed.
+*/
+QmlTimeLine::~QmlTimeLine()
+{
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ iter.key()->_t = 0;
+
+ delete d; d = 0;
+}
+
+/*!
+ \enum QmlTimeLine::SyncMode
+ */
+
+/*!
+ Return the timeline's synchronization mode.
+ */
+QmlTimeLine::SyncMode QmlTimeLine::syncMode() const
+{
+ return d->syncMode;
+}
+
+/*!
+ Set the timeline's synchronization mode to \a syncMode.
+ */
+void QmlTimeLine::setSyncMode(SyncMode syncMode)
+{
+ d->syncMode = syncMode;
+}
+
+/*!
+ Pause \a obj for \a time milliseconds.
+*/
+void QmlTimeLine::pause(QmlTimeLineObject &obj, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
+ d->add(obj, op);
+}
+
+/*!
+ Execute the \a event.
+ */
+void QmlTimeLine::execute(const QmlTimeLineEvent &event)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, event);
+ d->add(*event.eventObject(), op);
+}
+
+/*!
+ Set the \a value of \a timeLineValue.
+*/
+void QmlTimeLine::set(QmlTimeLineValue &timeLineValue, qreal value)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Set, 0, value, 0., d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate. Although the \a acceleration is technically
+ a deceleration, it should always be positive. The QmlTimeLine will ensure
+ that the deceleration is in the opposite direction to the initial velocity.
+*/
+int QmlTimeLine::accel(QmlTimeLineValue &timeLineValue, qreal velocity, qreal acceleration)
+{
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ \overload
+
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate over a maximum distance of maxDistance.
+
+ If necessary, QmlTimeLine will reduce the acceleration to ensure that the
+ entire operation does not require a move of more than \a maxDistance.
+ \a maxDistance should always be positive.
+*/
+int QmlTimeLine::accel(QmlTimeLineValue &timeLineValue, qreal velocity, qreal acceleration, qreal maxDistance)
+{
+ Q_ASSERT(acceleration >= 0.0f && maxDistance >= 0.0f);
+
+ qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
+ if (maxAccel > acceleration)
+ acceleration = maxAccel;
+
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero over the given
+ \a distance. This is like accel(), but the QmlTimeLine calculates the exact
+ deceleration to use.
+
+ \a distance should be positive.
+*/
+int QmlTimeLine::accelDistance(QmlTimeLineValue &timeLineValue, qreal velocity, qreal distance)
+{
+ if (distance == 0.0f || velocity == 0.0f)
+ return -1;
+ Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
+
+ int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value to the given
+ \a destination value over \a time milliseconds.
+*/
+void QmlTimeLine::move(QmlTimeLineValue &timeLineValue, qreal destination, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value to the given \a destination
+ value over \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::move(QmlTimeLineValue &timeLineValue, qreal destination, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, QmlTimeLineEvent(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value by the \a change amount
+ over \a time milliseconds.
+*/
+void QmlTimeLine::moveBy(QmlTimeLineValue &timeLineValue, qreal change, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value by the \a change amount over
+ \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::moveBy(QmlTimeLineValue &timeLineValue, qreal change, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, QmlTimeLineEvent(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Cancel (but don't complete) all scheduled actions for \a timeLineValue.
+*/
+void QmlTimeLine::reset(QmlTimeLineValue &timeLineValue)
+{
+ if (!timeLineValue._t)
+ return;
+ if (timeLineValue._t != this) {
+ qWarning() << "QmlTimeLine: Cannot reset a QmlTimeLineValue owned by another timeline.";
+ return;
+ }
+ remove(&timeLineValue);
+ timeLineValue._t = 0;
+}
+
+int QmlTimeLine::duration() const
+{
+ return -1;
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of \a syncTo
+ within this timeline.
+
+ Following operations on \a timeLineValue in this timeline will be scheduled after
+ all the currently scheduled actions on \a syncTo are complete. In
+ psuedo-code this is equivalent to:
+ \code
+ QmlTimeLine::pause(timeLineValue, min(0, length_of(syncTo) - length_of(timeLineValue)))
+ \endcode
+*/
+void QmlTimeLine::sync(QmlTimeLineValue &timeLineValue, QmlTimeLineValue &syncTo)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
+ if (iter == d->ops.end())
+ return;
+ int length = iter->length;
+
+ iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, length);
+ } else {
+ int glength = iter->length;
+ pause(timeLineValue, length - glength);
+ }
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of the longest
+ action cursrently scheduled in the timeline.
+
+ In psuedo-code, this is equivalent to:
+ \code
+ QmlTimeLine::pause(timeLineValue, length_of(timeline) - length_of(timeLineValue))
+ \endcode
+*/
+void QmlTimeLine::sync(QmlTimeLineValue &timeLineValue)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, d->length);
+ } else {
+ pause(timeLineValue, d->length - iter->length);
+ }
+}
+
+/*
+ Synchronize all currently and future scheduled values in this timeline to
+ the longest action currently scheduled.
+
+ For example:
+ \code
+ value1->setValue(0.);
+ value2->setValue(0.);
+ value3->setValue(0.);
+ QmlTimeLine tl;
+ ...
+ tl.move(value1, 10, 200);
+ tl.move(value2, 10, 100);
+ tl.sync();
+ tl.move(value2, 20, 100);
+ tl.move(value3, 20, 100);
+ \endcode
+
+ will result in:
+
+ \table
+ \header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms
+ \row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10
+ \row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0
+ \row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0
+ \endtable
+*/
+
+/*void QmlTimeLine::sync()
+{
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ pause(*iter.key(), d->length - iter->length);
+ d->syncPoint = d->length;
+}*/
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+void QmlTimeLine::setSyncPoint(int sp)
+{
+ d->syncPoint = sp;
+}
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+int QmlTimeLine::syncPoint() const
+{
+ return d->syncPoint;
+}
+
+/*!
+ Returns true if the timeline is active. An active timeline is one where
+ QmlTimeLineValue actions are still pending.
+*/
+bool QmlTimeLine::isActive() const
+{
+ return !d->ops.isEmpty();
+}
+
+/*!
+ Completes the timeline. All queued actions are played to completion, and then discarded. For example,
+ \code
+ QmlTimeLineValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.complete();
+ // v.value() == 100.
+ \endcode
+*/
+void QmlTimeLine::complete()
+{
+ d->advance(d->length);
+}
+
+/*!
+ Resets the timeline. All queued actions are discarded and QmlTimeLineValue's retain their current value. For example,
+ \code
+ QmlTimeLineValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.clear();
+ // v.value() == 50.
+ \endcode
+*/
+void QmlTimeLine::clear()
+{
+ for (QmlTimeLinePrivate::Ops::ConstIterator iter = d->ops.begin(); iter != d->ops.end(); ++iter)
+ iter.key()->_t = 0;
+ d->ops.clear();
+ d->length = 0;
+ d->syncPoint = 0;
+ //XXX need stop here?
+}
+
+int QmlTimeLine::time() const
+{
+ return d->prevTime;
+}
+
+/*!
+ \fn void QmlTimeLine::updated()
+
+ Emitted each time the timeline modifies QmlTimeLineValues. Even if multiple
+ QmlTimeLineValues are changed, this signal is only emitted once for each clock tick.
+*/
+
+void QmlTimeLine::updateCurrentTime(int v)
+{
+ if (d->syncAdj == -1)
+ d->syncAdj = v;
+ v -= d->syncAdj;
+
+ int timeChanged = v - d->prevTime;
+#if 0
+ if (!timeChanged)
+ return;
+#endif
+ d->prevTime = v;
+ d->advance(timeChanged);
+ emit updated();
+
+ // Do we need to stop the clock?
+ if (d->ops.isEmpty()) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = false;
+ emit completed();
+ } /*else if (pauseTime > 0) {
+ GfxClock::cancelClock();
+ d->prevTime = 0;
+ GfxClock::pauseFor(pauseTime);
+ d->syncAdj = 0;
+ d->clockRunning = false;
+ }*/ else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+ d->syncAdj = 0;
+ start();
+ }
+}
+
+bool operator<(const QPair<int, Update> &lhs,
+ const QPair<int, Update> &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+int QmlTimeLinePrivate::advance(int t)
+{
+ int pauseTime = -1;
+
+ // XXX - surely there is a more efficient way?
+ do {
+ pauseTime = -1;
+ // Minimal advance time
+ int advanceTime = t;
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ++iter) {
+ TimeLine &tl = *iter;
+ Op &op = tl.ops.first();
+ int length = op.length - tl.consumedOpLength;
+
+ if (length < advanceTime) {
+ advanceTime = length;
+ if (advanceTime == 0)
+ break;
+ }
+ }
+ t -= advanceTime;
+
+ // Process until then. A zero length advance time will only process
+ // sets.
+ QList<QPair<int, Update> > updates;
+
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
+ QmlTimeLineValue *v = static_cast<QmlTimeLineValue *>(iter.key());
+ TimeLine &tl = *iter;
+ Q_ASSERT(!tl.ops.isEmpty());
+
+ do {
+ Op &op = tl.ops.first();
+ if (advanceTime == 0 && op.length != 0)
+ continue;
+
+ if (tl.consumedOpLength == 0 &&
+ op.type != Op::Pause &&
+ op.type != Op::Execute)
+ tl.base = v->value();
+
+ if ((tl.consumedOpLength + advanceTime) == op.length) {
+ if (op.type == Op::Execute) {
+ updates << qMakePair(op.order, Update(op.event));
+ } else {
+ bool changed = false;
+ qreal val = value(op, op.length, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ }
+ tl.length -= qMin(advanceTime, tl.length);
+ tl.consumedOpLength = 0;
+ tl.ops.removeFirst();
+ } else {
+ tl.consumedOpLength += advanceTime;
+ bool changed = false;
+ qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ tl.length -= qMin(advanceTime, tl.length);
+ break;
+ }
+
+ } while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
+
+
+ if (tl.ops.isEmpty()) {
+ iter = ops.erase(iter);
+ v->_t = 0;
+ } else {
+ if (tl.ops.first().type == Op::Pause && pauseTime != 0) {
+ int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
+ if (pauseTime == -1 || opPauseTime < pauseTime)
+ pauseTime = opPauseTime;
+ } else {
+ pauseTime = 0;
+ }
+ ++iter;
+ }
+ }
+
+ length -= qMin(length, advanceTime);
+ syncPoint -= advanceTime;
+
+ qSort(updates.begin(), updates.end());
+ updateQueue = &updates;
+ for (int ii = 0; ii < updates.count(); ++ii) {
+ const Update &v = updates.at(ii).second;
+ if (v.g)
+ v.g->setValue(v.v);
+ else
+ v.e.execute();
+ }
+ updateQueue = 0;
+ } while(t);
+
+ return pauseTime;
+}
+
+void QmlTimeLine::remove(QmlTimeLineObject *v)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
+ Q_ASSERT(iter != d->ops.end());
+
+ int len = iter->length;
+ d->ops.erase(iter);
+ if (len == d->length) {
+ // We need to recalculate the length
+ d->length = 0;
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter) {
+
+ if (iter->length > d->length)
+ d->length = iter->length;
+
+ }
+ }
+ if (d->ops.isEmpty()) {
+ stop();
+ d->clockRunning = false;
+ } else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+
+ if (d->syncMode == QmlTimeLine::LocalSync) {
+ d->syncAdj = -1;
+ } else {
+ d->syncAdj = 0;
+ }
+ start();
+ }
+
+ if (d->updateQueue) {
+ for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
+ if (d->updateQueue->at(ii).second.g == v ||
+ d->updateQueue->at(ii).second.e.eventObject() == v) {
+ d->updateQueue->removeAt(ii);
+ --ii;
+ }
+ }
+ }
+
+
+}
+
+/*!
+ \internal
+ \class QmlTimeLineValue
+ \ingroup group_animation
+ \brief The QmlTimeLineValue class provides a value that can be modified by QmlTimeLine.
+*/
+
+/*!
+ \fn QmlTimeLineValue::QmlTimeLineValue(qreal value = 0)
+
+ Construct a new QmlTimeLineValue with an initial \a value.
+*/
+
+/*!
+ \fn qreal QmlTimeLineValue::value() const
+
+ Return the current value.
+*/
+
+/*!
+ \fn void QmlTimeLineValue::setValue(qreal value)
+
+ Set the current \a value.
+*/
+
+/*!
+ \fn QmlTimeLine *QmlTimeLineValue::timeLine() const
+
+ If a QmlTimeLine is operating on this value, return a pointer to it,
+ otherwise return null.
+*/
+
+
+QmlTimeLineObject::QmlTimeLineObject()
+: _t(0)
+{
+}
+
+QmlTimeLineObject::~QmlTimeLineObject()
+{
+ if (_t) {
+ _t->remove(this);
+ _t = 0;
+ }
+}
+
+QmlTimeLineEvent::QmlTimeLineEvent()
+: d0(0), d1(0), d2(0)
+{
+}
+
+QmlTimeLineEvent::QmlTimeLineEvent(const QmlTimeLineEvent &o)
+: d0(o.d0), d1(o.d1), d2(o.d2)
+{
+}
+
+QmlTimeLineEvent &QmlTimeLineEvent::operator=(const QmlTimeLineEvent &o)
+{
+ d0 = o.d0;
+ d1 = o.d1;
+ d2 = o.d2;
+ return *this;
+}
+
+void QmlTimeLineEvent::execute() const
+{
+ d0(d1);
+}
+
+QmlTimeLineObject *QmlTimeLineEvent::eventObject() const
+{
+ return d2;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/timeline/qmltimeline.h b/src/declarative/timeline/qmltimeline.h
new file mode 100644
index 0000000..23bdd64
--- /dev/null
+++ b/src/declarative/timeline/qmltimeline.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTIMELINE_H
+#define QMLTIMELINE_H
+
+#include <QtCore/QObject>
+#include <QtCore/QAbstractAnimation>
+#include <QtDeclarative/qfxglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QEasingCurve;
+class QmlTimeLineValue;
+class QmlTimeLineEvent;
+struct QmlTimeLinePrivate;
+class QmlTimeLineObject;
+class Q_DECLARATIVE_EXPORT QmlTimeLine : public QAbstractAnimation
+{
+Q_OBJECT
+public:
+ QmlTimeLine(QObject *parent = 0);
+ ~QmlTimeLine();
+
+ enum SyncMode { LocalSync, GlobalSync };
+ SyncMode syncMode() const;
+ void setSyncMode(SyncMode);
+
+ void pause(QmlTimeLineObject &, int);
+ void execute(const QmlTimeLineEvent &);
+ void set(QmlTimeLineValue &, qreal);
+
+ int accel(QmlTimeLineValue &, qreal velocity, qreal accel);
+ int accel(QmlTimeLineValue &, qreal velocity, qreal accel, qreal maxDistance);
+ int accelDistance(QmlTimeLineValue &, qreal velocity, qreal distance);
+
+ void move(QmlTimeLineValue &, qreal destination, int time = 500);
+ void move(QmlTimeLineValue &, qreal destination, const QEasingCurve &, int time = 500);
+ void moveBy(QmlTimeLineValue &, qreal change, int time = 500);
+ void moveBy(QmlTimeLineValue &, qreal change, const QEasingCurve &, int time = 500);
+
+ void sync();
+ void setSyncPoint(int);
+ int syncPoint() const;
+
+ void sync(QmlTimeLineValue &);
+ void sync(QmlTimeLineValue &, QmlTimeLineValue &);
+
+ void reset(QmlTimeLineValue &);
+
+ void complete();
+ void clear();
+ bool isActive() const;
+
+ int time() const;
+
+ virtual int duration() const;
+Q_SIGNALS:
+ void updated();
+ void completed();
+
+protected:
+ virtual void updateCurrentTime(int);
+
+private:
+ void remove(QmlTimeLineObject *);
+ friend class QmlTimeLineObject;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLinePrivate *d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineObject
+{
+public:
+ QmlTimeLineObject();
+ virtual ~QmlTimeLineObject();
+
+protected:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLine *_t;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineValue : public QmlTimeLineObject
+{
+public:
+ QmlTimeLineValue(qreal v = 0.) : _v(v) {}
+
+ qreal value() const { return _v; }
+ virtual void setValue(qreal v) { _v = v; }
+
+ QmlTimeLine *timeLine() const { return _t; }
+
+ operator qreal() const { return _v; }
+ QmlTimeLineValue &operator=(qreal v) { setValue(v); return *this; }
+private:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ qreal _v;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineEvent
+{
+public:
+ QmlTimeLineEvent();
+ QmlTimeLineEvent(const QmlTimeLineEvent &o);
+
+ template<class T, void (T::*method)()>
+ QmlTimeLineEvent(QmlTimeLineObject *b, T *c)
+ {
+ d0 = &callFunc<T, method>;
+ d1 = (void *)c;
+ d2 = b;
+ }
+
+ template<class T, void (T::*method)()>
+ static QmlTimeLineEvent timeLineEvent(QmlTimeLineObject *b, T *c)
+ {
+ QmlTimeLineEvent rv;
+ rv.d0 = &callFunc<T, method>;
+ rv.d1 = (void *)c;
+ rv.d2 = b;
+ return rv;
+ }
+
+ QmlTimeLineEvent &operator=(const QmlTimeLineEvent &o);
+ void execute() const;
+ QmlTimeLineObject *eventObject() const;
+
+private:
+ typedef void (*CallFunc)(void *c);
+
+ template <class T, void (T::*method)()>
+ static void callFunc(void *c)
+ {
+ T *cls = (T *)c;
+ (cls->*method)();
+ }
+ CallFunc d0;
+ void *d1;
+ QmlTimeLineObject *d2;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/timeline/qmltimelinevalueproxy.h b/src/declarative/timeline/qmltimelinevalueproxy.h
new file mode 100644
index 0000000..9ecdba1
--- /dev/null
+++ b/src/declarative/timeline/qmltimelinevalueproxy.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTIMELINEVALUEPROXY_H
+#define QMLTIMELINEVALUEPROXY_H
+
+#include <QtDeclarative/qmltimeline.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<class T>
+class QmlTimeLineValueProxy : public QmlTimeLineValue
+{
+public:
+ QmlTimeLineValueProxy(T *cls, void (T::*func)(qreal), qreal v = 0.)
+ : QmlTimeLineValue(v), _class(cls), _setFunctionReal(func), _setFunctionInt(0)
+ {
+ Q_ASSERT(_class);
+ }
+
+ QmlTimeLineValueProxy(T *cls, void (T::*func)(int), qreal v = 0.)
+ : QmlTimeLineValue(v), _class(cls), _setFunctionReal(0), _setFunctionInt(func)
+ {
+ Q_ASSERT(_class);
+ }
+
+ virtual void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ if (_setFunctionReal) (_class->*_setFunctionReal)(v);
+ else if (_setFunctionInt) (_class->*_setFunctionInt)((int)v);
+ }
+
+private:
+ T *_class;
+ void (T::*_setFunctionReal)(qreal);
+ void (T::*_setFunctionInt)(int);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif//QMLTIMELINEVALUEPROXY_H
diff --git a/src/declarative/timeline/timeline.pri b/src/declarative/timeline/timeline.pri
new file mode 100644
index 0000000..a7b3cb9
--- /dev/null
+++ b/src/declarative/timeline/timeline.pri
@@ -0,0 +1,7 @@
+SOURCES += \
+ timeline/qmltimeline.cpp \
+
+HEADERS += \
+ timeline/qmltimeline.h \
+ timeline/qmltimelinevalueproxy.h \
+
diff --git a/src/declarative/util/qbindablemap.cpp b/src/declarative/util/qbindablemap.cpp
new file mode 100644
index 0000000..c8c8ced
--- /dev/null
+++ b/src/declarative/util/qbindablemap.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbindablemap.h"
+#include <qmlopenmetaobject.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+//QBindableMapMetaObject lets us listen for changes coming from QML
+//so we can emit the changed signal.
+class QBindableMapMetaObject : public QmlOpenMetaObject
+{
+public:
+ QBindableMapMetaObject(QBindableMap *obj) : QmlOpenMetaObject(obj)
+ {
+ map = obj;
+ }
+
+protected:
+ virtual void propertyWrite(int index)
+ {
+ map->emitChanged(QLatin1String(name(index)));
+ }
+
+private:
+ QBindableMap *map;
+};
+
+/*!
+ \class QBindableMap
+ \brief The QBindableMap class allows you to set key-value pairs that can be used in bindings.
+
+ QBindableMap provides a convenient way to expose domain data to the UI layer.
+ The following example shows how you might declare data in C++ and then
+ access it in QML.
+
+ Setup in C++:
+ \code
+ //create our data
+ QBindableMap ownerData;
+ ownerData.setValue("name", QVariant(QString("John Smith")));
+ ownerData.setValue("phone", QVariant(QString("555-5555")));
+
+ //expose it to the UI layer
+ QmlContext *ctxt = view->bindContext();
+ ctxt->setProperty("owner", &data);
+ \endcode
+
+ Then, in QML:
+ \code
+ Text { text: owner.name }
+ Text { text: owner.phone }
+ \endcode
+
+ The binding is dynamic - whenever a key's value is updated, anything bound to that
+ key will be updated as well.
+
+ To detect value changes made in the UI layer you can connect to the changed() signal.
+ However, note that changed() is \b NOT emitted when changes are made by calling setValue()
+ or clearValue() - it is only emitted when a value is updated from QML.
+*/
+
+// is there a more efficient way to store/return keys?
+// (or should we just provide an iterator or something else instead?)
+// can we provide a way to clear keys?
+// do we want to make any claims regarding key ordering?
+// should we have signals for insertion and and deletion -- becoming more model like
+// should we emit change for our own changes as well?
+// Bug or Feature?: values can be created in QML (owner.somethingElse = "Hello") will create somethingElse property. (need to verify if this is actually the case)
+// Bug or Feature?: all values are read-write (there are no read-only values)
+
+/*!
+ Constructs a bindable map with parent object \a parent.
+*/
+QBindableMap::QBindableMap(QObject *parent)
+: QObject(parent)
+{
+ m_mo = new QBindableMapMetaObject(this);
+}
+
+/*!
+ Destroys the bindable map.
+*/
+QBindableMap::~QBindableMap()
+{
+}
+
+/*!
+ Clears the value (if any) associated with \a key.
+*/
+void QBindableMap::clearValue(const QString &key)
+{
+ //m_keys.remove(); //###
+ m_mo->setValue(key.toLatin1(), QVariant());
+ //emit changed(key);
+}
+
+/*!
+ Returns the value associated with \a key.
+
+ If no value has been set for this key (or if the value has been cleared),
+ an invalid QVariant is returned.
+*/
+QVariant QBindableMap::value(const QString &key) const
+{
+ return m_mo->value(key.toLatin1());
+}
+
+/*!
+ Sets the value associated with \a key to \a value.
+
+ If the key doesn't exist, it is automatically created.
+*/
+void QBindableMap::setValue(const QString &key, QVariant value)
+{
+ if (!m_keys.contains(key))
+ m_keys.append(key);
+ m_mo->setValue(key.toLatin1(), value);
+ //emit changed(key);
+}
+
+/*!
+ Returns the list of keys.
+
+ Keys that have been cleared will still appear in this list, even though their
+ associated values are invalid QVariants.
+*/
+QStringList QBindableMap::keys() const
+{
+ return m_keys;
+}
+
+/*!
+ \fn void QBindableMap::changed(const QString &key)
+ This signal is emitted whenever one of the values in the map is changed. \a key
+ is the key corresponding to the value that was changed.
+ */
+
+void QBindableMap::emitChanged(const QString &key)
+{
+ emit changed(key);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qbindablemap.h b/src/declarative/util/qbindablemap.h
new file mode 100644
index 0000000..c76928d
--- /dev/null
+++ b/src/declarative/util/qbindablemap.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBINDABLEMAP_H
+#define QBINDABLEMAP_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QBindableMapMetaObject;
+class Q_DECLARATIVE_EXPORT QBindableMap : public QObject
+{
+ Q_OBJECT
+public:
+ QBindableMap(QObject *parent = 0);
+ virtual ~QBindableMap();
+
+ QVariant value(const QString &key) const;
+ void setValue(const QString &key, QVariant value);
+ void clearValue(const QString &key);
+
+ Q_INVOKABLE QStringList keys() const;
+
+Q_SIGNALS:
+ void changed(const QString &key);
+
+private:
+ Q_DISABLE_COPY(QBindableMap)
+ void emitChanged(const QString &key);
+ QBindableMapMetaObject *m_mo;
+ QStringList m_keys;
+ friend class QBindableMapMetaObject;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qfxglobal.h b/src/declarative/util/qfxglobal.h
new file mode 100644
index 0000000..6ba9409
--- /dev/null
+++ b/src/declarative/util/qfxglobal.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXGLOBAL_H
+#define QFXGLOBAL_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QObject>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+#if defined(QT_OPENGL_ES_1)
+#define QFX_CONFIGURATION_OPENGL1
+#elif defined(QT_OPENGL_ES_2)
+#define QFX_CONFIGURATION_OPENGL2
+#else
+#define QFX_CONFIGURATION_SOFTWARE
+#endif
+
+/*
+ The choices of renderer are:
+ QFX_RENDER_QPAINTER
+ QFX_RENDER_OPENGL1
+ QFX_RENDER_OPENGL2
+ To simplify code, if either of the OpenGL renderers are used,
+ QFX_RENDER_OPENGL is also defined.
+*/
+
+#if defined(QFX_CONFIGURATION_OPENGL2)
+
+#define QFX_RENDER_OPENGL
+#define QFX_RENDER_OPENGL2
+
+#elif defined(QFX_CONFIGURATION_OPENGL1)
+
+#define QFX_RENDER_OPENGL
+#define QFX_RENDER_OPENGL1
+
+#elif defined(QFX_CONFIGURATION_SOFTWARE)
+
+#define QFX_RENDER_QPAINTER
+
+#endif
+
+#define DEFINE_BOOL_CONFIG_OPTION(name, var) \
+ static bool name() \
+ { \
+ static enum { Yes, No, Unknown } status = Unknown; \
+ if (status == Unknown) { \
+ QByteArray v = qgetenv(#var); \
+ bool value = !v.isEmpty() && v != "0" && v != "false"; \
+ if (value) status = Yes; \
+ else status = No; \
+ } \
+ return status == Yes; \
+ }
+
+struct QFx_DerivedObject : public QObject
+{
+ void setParent_noEvent(QObject *parent) {
+ bool sce = d_ptr->sendChildEvents;
+ d_ptr->sendChildEvents = false;
+ setParent(parent);
+ d_ptr->sendChildEvents = sce;
+ }
+};
+
+/*!
+ Makes the \a object a child of \a parent. Note that when using this method,
+ neither \a parent nor the object's previous parent (if it had one) will
+ receive ChildRemoved or ChildAdded events.
+*/
+inline void QFx_setParent_noEvent(QObject *object, QObject *parent)
+{
+ static_cast<QFx_DerivedObject *>(object)->setParent_noEvent(parent);
+}
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXGLOBAL_H
diff --git a/src/declarative/util/qfxperf.cpp b/src/declarative/util/qfxperf.cpp
new file mode 100644
index 0000000..e4f0c53
--- /dev/null
+++ b/src/declarative/util/qfxperf.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxperf.h"
+
+
+QT_BEGIN_NAMESPACE
+Q_DEFINE_PERFORMANCE_LOG(QFxPerf, "QFx") {
+ Q_DEFINE_PERFORMANCE_METRIC(QmlParsing, "Compilation: QML Parsing")
+ Q_DEFINE_PERFORMANCE_METRIC(Compilation, " QML Compilation")
+ Q_DEFINE_PERFORMANCE_METRIC(VMEExecution, "Execution: QML VME Execution")
+ Q_DEFINE_PERFORMANCE_METRIC(BindInit, "BindValue Initialization")
+ Q_DEFINE_PERFORMANCE_METRIC(BindValue, "BindValue execution")
+ Q_DEFINE_PERFORMANCE_METRIC(BindValueSSE, "BindValue execution SSE")
+ Q_DEFINE_PERFORMANCE_METRIC(BindValueQt, "BindValue execution QtScript")
+ Q_DEFINE_PERFORMANCE_METRIC(BindableValueUpdate, "QmlBindableValue::update")
+ Q_DEFINE_PERFORMANCE_METRIC(PixmapLoad, "Pixmap loading")
+ Q_DEFINE_PERFORMANCE_METRIC(FontDatabase, "Font database creation")
+ Q_DEFINE_PERFORMANCE_METRIC(QFxPathViewPathCache, "FX Items: QFxPathView: Path cache")
+ Q_DEFINE_PERFORMANCE_METRIC(CreateParticle, " QFxParticles: Particle creation")
+ Q_DEFINE_PERFORMANCE_METRIC(ItemComponentComplete, " QFxItem::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(ImageComponentComplete, " QFxImage::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(ComponentInstanceComponentComplete, " QFxComponentInstance::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(BaseLayoutComponentComplete, " QFxBaseLayout::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(TextComponentComplete, " QFxText::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(QFxText_setText, " QFxText::setText")
+ Q_DEFINE_PERFORMANCE_METRIC(AddScript, "QmlScript::addScriptToEngine")
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qfxperf.h b/src/declarative/util/qfxperf.h
new file mode 100644
index 0000000..9fcf1d6
--- /dev/null
+++ b/src/declarative/util/qfxperf.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef _QFXPERF_H_
+#define _QFXPERF_H_
+
+#include "qperformancelog.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+Q_DECLARE_PERFORMANCE_LOG(QFxPerf) {
+ Q_DECLARE_PERFORMANCE_METRIC(QmlParsing)
+
+ Q_DECLARE_PERFORMANCE_METRIC(Compilation)
+ Q_DECLARE_PERFORMANCE_METRIC(VMEExecution)
+
+ Q_DECLARE_PERFORMANCE_METRIC(BindInit)
+ Q_DECLARE_PERFORMANCE_METRIC(BindValue)
+ Q_DECLARE_PERFORMANCE_METRIC(BindValueSSE)
+ Q_DECLARE_PERFORMANCE_METRIC(BindValueQt)
+ Q_DECLARE_PERFORMANCE_METRIC(BindableValueUpdate)
+ Q_DECLARE_PERFORMANCE_METRIC(PixmapLoad)
+ Q_DECLARE_PERFORMANCE_METRIC(FontDatabase)
+ Q_DECLARE_PERFORMANCE_METRIC(QFxPathViewPathCache)
+ Q_DECLARE_PERFORMANCE_METRIC(CreateParticle)
+ Q_DECLARE_PERFORMANCE_METRIC(ItemComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(ImageComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(ComponentInstanceComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(BaseLayoutComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(TextComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(QFxText_setText)
+ Q_DECLARE_PERFORMANCE_METRIC(AddScript)
+}
+
+#endif // _QFXPERF_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp
new file mode 100644
index 0000000..0d5b796
--- /dev/null
+++ b/src/declarative/util/qfxview.cpp
@@ -0,0 +1,570 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptvalueiterator.h"
+#include "qdebug.h"
+#include "qtimer.h"
+#include "qevent.h"
+#include "qdir.h"
+#include "qcoreapplication.h"
+#include "qfontdatabase.h"
+#include "qicon.h"
+#include "qurl.h"
+#include "qboxlayout.h"
+#include "qbasictimer.h"
+
+#include "qmlbindablevalue.h"
+#include "qml.h"
+#include "qfxitem.h"
+#include "qperformancelog.h"
+#include "qfxperf.h"
+
+#include "qfxview.h"
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmldebugger.h>
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(itemTreeDump, ITEMTREE_DUMP);
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER);
+
+static QVariant stringToPixmap(const QString &str)
+{
+ //XXX need to use correct paths
+ return QVariant(QPixmap(str));
+}
+
+static QVariant stringToIcon(const QString &str)
+{
+ //XXX need to use correct paths
+ return QVariant(QIcon(str));
+}
+
+static QVariant stringToKeySequence(const QString &str)
+{
+ return QVariant::fromValue(QKeySequence(str));
+}
+
+static QVariant stringToUrl(const QString &str)
+{
+ return QVariant(QUrl(str));
+}
+
+class QFxViewPrivate
+{
+public:
+ QFxViewPrivate(QFxView *w)
+ : q(w), root(0), component(0), resizable(false) {}
+
+ QFxView *q;
+ QFxItem *root;
+
+ QUrl source;
+ QString qml;
+
+ QmlEngine engine;
+ QmlComponent *component;
+ QBasicTimer resizetimer;
+
+ QSize initialSize;
+ bool resizable;
+
+ void init();
+};
+
+/*!
+ \class QFxView
+ \brief The QFxView class provides a widget for displaying a Qt Declarative user interface.
+
+ QFxView currently provides a minimal interface for displaying QML
+ files, and connecting between QML and C++ Qt objects.
+
+ Typical usage:
+ \code
+ ...
+ QFxView *view = new QFxView(this);
+ vbox->addWidget(view);
+
+ QUrl url(fileName);
+ view->setUrl(url);
+ ...
+ view->execute();
+ ...
+ \endcode
+*/
+
+/*!
+ \fn QFxView::QFxView(QWidget *parent)
+
+ Constructs a QFxView with the given \a parent.
+*/
+QFxView::QFxView(QWidget *parent)
+: QSimpleCanvas(parent), d(new QFxViewPrivate(this))
+{
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+}
+
+/*!
+ \fn QFxView::QFxView(QSimpleCanvas::CanvasMode mode, QWidget *parent)
+ \internal
+ Constructs a QFxView with the given \a parent. The canvas
+ \a mode can be QSimpleCanvas::GraphicsView or
+ QSimpleCanvas::SimpleCanvas.
+*/
+QFxView::QFxView(QSimpleCanvas::CanvasMode mode, QWidget *parent)
+: QSimpleCanvas(mode, parent), d(new QFxViewPrivate(this))
+{
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+}
+
+void QFxViewPrivate::init()
+{
+ // XXX: These need to be put in a central location for this kind of thing
+ qRegisterMetaType<QFxAnchorLine>("QFxAnchorLine");
+
+ QmlMetaType::registerCustomStringConverter(QVariant::Pixmap, &stringToPixmap);
+ QmlMetaType::registerCustomStringConverter(QVariant::Icon, &stringToIcon);
+ QmlMetaType::registerCustomStringConverter(QVariant::KeySequence, &stringToKeySequence);
+ QmlMetaType::registerCustomStringConverter(QVariant::Url, &stringToUrl);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::FontDatabase> perf;
+#endif
+ QFontDatabase database;
+}
+
+/*!
+ The destructor clears the view's \l {QFxItem} {items} and
+ deletes the internal representation.
+
+ \sa clearItems()
+ */
+QFxView::~QFxView()
+{
+ clearItems();
+ delete d; d = 0;
+}
+
+/*!
+ Sets the source to the \a url. The QML string is set to
+ empty.
+ */
+void QFxView::setUrl(const QUrl& url)
+{
+ d->source = url;
+ d->qml = QString();
+}
+
+/*!
+ Sets the source to the URL from the \a filename, and sets
+ the QML string to \a qml.
+ */
+void QFxView::setQml(const QString &qml, const QString &filename)
+{
+ d->source = QUrl::fromLocalFile(filename);
+ d->qml = qml;
+}
+
+/*!
+ Returns the QML string.
+ */
+QString QFxView::qml() const
+{
+ return d->qml;
+}
+
+/*!
+ Returns a pointer to the QmlEngine used for instantiating
+ QML Components.
+ */
+QmlEngine* QFxView::engine()
+{
+ return &d->engine;
+}
+
+/*!
+ This function returns the root of the context hierarchy. Each QML
+ component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are
+ arranged hierarchically and this hierarchy is managed by the
+ QmlEngine.
+ */
+QmlContext* QFxView::rootContext()
+{
+ return d->engine.rootContext();
+}
+
+/*!
+ Displays the Qt Declarative user interface.
+*/
+void QFxView::execute()
+{
+ if (d->qml.isEmpty()) {
+ d->component = new QmlComponent(&d->engine, d->source, this);
+ } else {
+ d->component = new QmlComponent(&d->engine, d->qml.toUtf8(), d->source);
+ }
+
+ if (!d->component->isLoading()) {
+ continueExecute();
+ } else {
+ connect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
+ }
+}
+
+/*!
+ \internal
+*/
+void QFxView::printErrorLine(const QmlError &error)
+{
+ QUrl url = error.url();
+ if (error.line() > 0 && error.column() > 0 &&
+ url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ qWarning() << qPrintable(line);
+
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ qWarning() << ind.constData();
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+ */
+void QFxView::continueExecute()
+{
+ disconnect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
+
+ if (!d->component){
+ qWarning() << "Error in loading" << d->source;
+ return;
+ }
+
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return;
+ }
+
+ QObject *obj = d->component->create();
+
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return;
+ }
+
+ if (obj) {
+ if (QFxItem *item = qobject_cast<QFxItem *>(obj)) {
+ item->QSimpleCanvasItem::setParent(QSimpleCanvas::root());
+
+ if (itemTreeDump())
+ item->dump();
+
+ if(qmlDebugger()) {
+ QmlDebugger *debugger = new QmlDebugger;
+ debugger->setDebugObject(item);
+ debugger->setCanvas(this);
+ debugger->show();
+ raise();
+ debugger->raise();
+ }
+
+ QPerformanceLog::displayData();
+ QPerformanceLog::clear();
+ d->root = item;
+ connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged()));
+ connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged()));
+ if (d->initialSize.height() <= 0 && d->root->width() > 0)
+ d->initialSize.setWidth(d->root->width());
+ if (d->initialSize.height() <= 0 && d->root->height() > 0)
+ d->initialSize.setHeight(d->root->height());
+ if (d->resizable) {
+ d->root->setWidth(width());
+ d->root->setHeight(height());
+ } else {
+ QSize sz(d->root->width(),d->root->height());
+ emit sceneResized(sz);
+ resize(sz);
+ }
+ } else if (QWidget *wid = qobject_cast<QWidget *>(obj)) {
+ window()->setAttribute(Qt::WA_OpaquePaintEvent, false);
+ window()->setAttribute(Qt::WA_NoSystemBackground, false);
+ if (!layout()) {
+ setLayout(new QVBoxLayout);
+ } else if (layout()->count()) {
+ // Hide the QGraphicsView in GV mode.
+ QLayoutItem *item = layout()->itemAt(0);
+ if (item->widget())
+ item->widget()->hide();
+ }
+ layout()->addWidget(wid);
+ emit sceneResized(wid->size());
+ }
+ }
+}
+
+/*! \fn void QFxView::sceneResized(QSize size)
+ This signal is emitted when the view is resized to \a size.
+ */
+
+/*!
+ \internal
+ */
+void QFxView::sizeChanged()
+{
+ // delay, so we catch both width and height changing.
+ d->resizetimer.start(0,this);
+}
+
+/*!
+ If the \l {QTimerEvent} {timer event} \a e is this
+ view's resize timer, sceneResized() is emitted.
+ */
+void QFxView::timerEvent(QTimerEvent* e)
+{
+ if (!e || e->timerId() == d->resizetimer.timerId()) {
+ if (d->root) {
+ QSize sz(d->root->width(),d->root->height());
+ emit sceneResized(sz);
+ //if (!d->resizable)
+ //resize(sz);
+ }
+ d->resizetimer.stop();
+ updateGeometry();
+ }
+}
+
+// modelled on QScrollArea::widgetResizable
+/*!
+ \property QFxView::contentResizable
+ \brief whether the view should resize the canvas contents
+
+ If this property is set to false (the default), the view
+ resizes with the root item in the QML.
+
+ If this property is set to true, the view will
+ automatically resize the root item.
+
+ Regardless of this property, the sizeHint of the view
+ is the initial size of the root item.
+*/
+
+void QFxView::setContentResizable(bool on)
+{
+ if (d->resizable != on) {
+ d->resizable = on;
+ if (d->root) {
+ if (on) {
+ d->root->setWidth(width());
+ d->root->setHeight(height());
+ } else {
+ d->root->setWidth(d->initialSize.width());
+ d->root->setHeight(d->initialSize.height());
+ }
+ }
+ }
+}
+
+bool QFxView::contentResizable() const
+{
+ return d->resizable;
+}
+
+
+/*!
+ The size hint is the size of the root item.
+*/
+QSize QFxView::sizeHint() const
+{
+ if (d->root) {
+ if (d->initialSize.width() <= 0)
+ d->initialSize.setWidth(d->root->width());
+ if (d->initialSize.height() <= 0)
+ d->initialSize.setHeight(d->root->height());
+ }
+ return d->initialSize;
+}
+
+/*!
+ Creates a \l{QmlComponent} {component} from the \a qml
+ string, and returns it as an \l {QFxItem} {item}. If the
+ \a parent item is provided, it becomes the new item's
+ parent. \a parent should be in this view's item hierarchy.
+ */
+QFxItem* QFxView::addItem(const QString &qml, QFxItem* parent)
+{
+ if (!d->root)
+ return 0;
+
+ QmlComponent component(&d->engine, qml.toUtf8(), QUrl());
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return 0;
+ }
+
+ QObject *obj = component.create();
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return 0;
+ }
+
+ if (obj){
+ QFxItem *item = static_cast<QFxItem *>(obj);
+ if (!parent)
+ parent = d->root;
+
+ item->setItemParent(parent);
+ return item;
+ }
+ return 0;
+}
+
+/*!
+ Deletes the view's \l {QFxItem} {items} and the \l {QmlEngine}
+ {QML engine's} Component cache.
+ */
+void QFxView::reset()
+{
+ clearItems();
+ d->engine.clearComponentCache();
+ d->initialSize = QSize();
+}
+
+/*!
+ Deletes the view's \l {QFxItem} {items}.
+ */
+void QFxView::clearItems()
+{
+ if (!d->root)
+ return;
+ delete d->root;
+ d->root = 0;
+}
+
+/*!
+ Returns the view's root \l {QFxItem} {item}.
+ */
+QFxItem *QFxView::root() const
+{
+ return d->root;
+}
+
+/*!
+ This function handles the \l {QResizeEvent} {resize event}
+ \a e.
+ */
+void QFxView::resizeEvent(QResizeEvent *e)
+{
+ if (d->resizable && d->root) {
+ d->root->setWidth(width());
+ d->root->setHeight(height());
+ }
+ QSimpleCanvas::resizeEvent(e);
+}
+
+/*! \fn void QFxView::focusInEvent(QFocusEvent *e)
+ This virtual function does nothing with the event \a e
+ in this class.
+ */
+void QFxView::focusInEvent(QFocusEvent *)
+{
+ // Do nothing (do not call QWidget::update())
+}
+
+
+/*! \fn void QFxView::focusOutEvent(QFocusEvent *e)
+ This virtual function does nothing with the event \a e
+ in this class.
+ */
+void QFxView::focusOutEvent(QFocusEvent *)
+{
+ // Do nothing (do not call QWidget::update())
+}
+
+/*!
+ \internal
+ */
+void QFxView::dumpRoot()
+{
+ root()->dump();
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qfxview.h b/src/declarative/util/qfxview.h
new file mode 100644
index 0000000..05bf005
--- /dev/null
+++ b/src/declarative/util/qfxview.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXVIEW_H
+#define QFXVIEW_H
+
+#include <QtCore/qdatetime.h>
+#include <QtGui/qgraphicssceneevent.h>
+#include <QtGui/qwidget.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qsimplecanvas.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxItem;
+class QmlEngine;
+class QmlContext;
+class QmlError;
+
+class QFxViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxView : public QSimpleCanvas
+{
+Q_OBJECT
+public:
+ explicit QFxView(QWidget *parent = 0);
+ QFxView(QSimpleCanvas::CanvasMode mode, QWidget* parent = 0);
+
+ virtual ~QFxView();
+
+ void setUrl(const QUrl&);
+ void setQml(const QString &qml, const QString &filename=QString());
+ QString qml() const;
+ QmlEngine* engine();
+ QmlContext* rootContext();
+ virtual void execute();
+ virtual void reset();
+
+ virtual QFxItem* addItem(const QString &qml, QFxItem* parent=0);
+ virtual void clearItems();
+
+ virtual QFxItem *root() const;
+
+ void setContentResizable(bool);
+ bool contentResizable() const;
+ QSize sizeHint() const;
+
+ void dumpRoot();
+
+ static void printErrorLine(const QmlError &);
+Q_SIGNALS:
+ void sceneResized(QSize size);
+
+private Q_SLOTS:
+ void continueExecute();
+ void sizeChanged();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+ void focusInEvent(QFocusEvent *);
+ void focusOutEvent(QFocusEvent *);
+ void timerEvent(QTimerEvent*);
+
+private:
+ friend class QFxViewPrivate;
+ QFxViewPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXVIEW_H
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
new file mode 100644
index 0000000..d4aea81
--- /dev/null
+++ b/src/declarative/util/qmlanimation.cpp
@@ -0,0 +1,2267 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlanimation.h"
+#include "qvariant.h"
+#include "qcolor.h"
+#include "qfile.h"
+#include "qmlpropertyvaluesource.h"
+#include "qml.h"
+#include "qmlanimation_p.h"
+#include "qmlbehaviour.h"
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
+#include <QtCore/qset.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsize.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <private/qmlstringconverters_p.h>
+#include <private/qvariantanimation_p.h>
+
+/* TODO:
+ Check for any memory leaks
+ easing should be a QEasingCurve-type property
+ All other XXXs
+*/
+
+QT_BEGIN_NAMESPACE
+
+QEasingCurve stringToCurve(const QString &curve)
+{
+ QEasingCurve easingCurve;
+
+ QString normalizedCurve = curve;
+ bool hasParams = curve.contains(QLatin1Char('('));
+ QStringList props;
+
+ if (hasParams) {
+ QString easeName = curve.trimmed();
+ if (!easeName.endsWith(QLatin1Char(')'))) {
+ qWarning("QEasingCurve: Unmatched perenthesis in easing function '%s'",
+ curve.toLatin1().constData());
+ return easingCurve;
+ }
+
+ int idx = easeName.indexOf(QLatin1Char('('));
+ QString prop_str =
+ easeName.mid(idx + 1, easeName.length() - 1 - idx - 1);
+ normalizedCurve = easeName.left(idx);
+
+ props = prop_str.split(QLatin1Char(','));
+ }
+
+ normalizedCurve = normalizedCurve.mid(4);
+ //XXX optimize?
+ int index = QEasingCurve::staticMetaObject.indexOfEnumerator("Type");
+ QMetaEnum me = QEasingCurve::staticMetaObject.enumerator(index);
+
+ int value = me.keyToValue(normalizedCurve.toLatin1().constData());
+ if (value < 0) {
+ //XXX print line number
+ qWarning("QEasingCurve: Unknown easing curve '%s'",
+ curve.toLatin1().constData());
+ value = 0;
+ }
+ easingCurve.setType((QEasingCurve::Type)value);
+
+ if (hasParams) {
+ foreach(const QString &str, props) {
+ int sep = str.indexOf(QLatin1Char(':'));
+
+ if (sep == -1) {
+ qWarning("QEasingCurve: Improperly specified property in easing function '%s'",
+ curve.toLatin1().constData());
+ return easingCurve;
+ }
+
+ QString propName = str.left(sep).trimmed();
+ bool isOk;
+ qreal propValue = str.mid(sep + 1).trimmed().toDouble(&isOk);
+
+ if (propName.isEmpty() || !isOk) {
+ qWarning("QEasingCurve: Improperly specified property in easing function '%s'",
+ curve.toLatin1().constData());
+ return easingCurve;
+ }
+
+ //XXX optimize
+ if (propName == QLatin1String("amplitude")) {
+ easingCurve.setAmplitude(propValue);
+ } else if (propName == QLatin1String("period")) {
+ easingCurve.setPeriod(propValue);
+ } else if (propName == QLatin1String("overshoot")) {
+ easingCurve.setOvershoot(propValue);
+ }
+ }
+ }
+
+ return easingCurve;
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlAbstractAnimation)
+
+/*!
+ \qmlclass Animation
+ \brief The Animation element is the base of all QML animations.
+
+ The Animation element cannot be used directly in a QML file. It exists
+ to provide a set of common properties and methods, available across all the
+ other animation types that inherit from it. Attempting to use the Animation
+ element directly will result in an error.
+*/
+
+/*!
+ \class QmlAbstractAnimation
+ \internal
+*/
+
+QmlAbstractAnimation::QmlAbstractAnimation(QObject *parent)
+: QmlPropertyValueSource(*(new QmlAbstractAnimationPrivate), parent)
+{
+}
+
+QmlAbstractAnimation::~QmlAbstractAnimation()
+{
+}
+
+QmlAbstractAnimation::QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent)
+: QmlPropertyValueSource(dd, parent)
+{
+}
+
+/*!
+ \qmlproperty bool Animation::running
+ This property holds whether the animation is currently running.
+
+ The \c running property can be set to declaratively control whether or not
+ an animation is running. The following example will animate a rectangle
+ whenever the \l MouseRegion is pressed.
+
+ \code
+ Rect {
+ width: 100; height: 100
+ x: NumericAnimation {
+ running: MyMouse.pressed
+ from: 0; to: 100
+ }
+ MouseRegion { id: MyMouse }
+ }
+ \endcode
+
+ Likewise, the \c running property can be read to determine if the animation
+ is running. In the following example the text element will indicate whether
+ or not the animation is running.
+
+ \code
+ NumericAnimation { id: MyAnimation }
+ Text { text: MyAnimation.running ? "Animation is running" : "Animation is not running" }
+ \endcode
+
+ Animations can also be started and stopped imperatively from JavaScript
+ using the \c start() and \c stop() methods.
+
+ By default, animations are not running.
+*/
+bool QmlAbstractAnimation::isRunning() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->running;
+}
+
+void QmlAbstractAnimationPrivate::commence()
+{
+ Q_Q(QmlAbstractAnimation);
+
+ q->prepare(userProperty.value);
+ q->qtAnimation()->start();
+ if (q->qtAnimation()->state() != QAbstractAnimation::Running) {
+ running = false;
+ emit q->completed();
+ }
+}
+
+void QmlAbstractAnimation::setRunning(bool r)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->running == r)
+ return;
+
+ if (d->group) {
+ qWarning("QmlAbstractAnimation: setRunning() cannot be used on non-root animation nodes");
+ return;
+ }
+
+ d->running = r;
+ if (d->running) {
+ if (!d->connectedTimeLine) {
+ QObject::connect(qtAnimation(), SIGNAL(finished()),
+ this, SLOT(timelineComplete()));
+ d->connectedTimeLine = true;
+ }
+ if (d->componentComplete)
+ d->commence();
+ else
+ d->startOnCompletion = true;
+ emit started();
+ } else {
+ if (d->finishPlaying) {
+ if (d->repeat)
+ qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1);
+ } else
+ qtAnimation()->stop();
+
+ emit completed();
+ }
+
+ emit runningChanged(d->running);
+}
+
+void QmlAbstractAnimation::classBegin()
+{
+ Q_D(QmlAbstractAnimation);
+ d->componentComplete = false;
+}
+
+void QmlAbstractAnimation::componentComplete()
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->startOnCompletion)
+ d->commence();
+ d->componentComplete = true;
+}
+
+/*!
+ \qmlproperty bool Animation::finishPlaying
+ This property holds whether the animation should finish playing when it is stopped.
+
+ If this true the animation will complete its current iteration when it
+ is stopped - either by setting the \c running property to false, or by
+ calling the \c stop() method. The \c complete() method is not effected
+ by this value.
+
+ This behaviour is most useful when the \c repeat property is set, as the
+ animation will finish playing normally but not restart.
+
+ By default, the finishPlaying property is not set.
+*/
+bool QmlAbstractAnimation::finishPlaying() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->finishPlaying;
+}
+
+void QmlAbstractAnimation::setFinishPlaying(bool f)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->finishPlaying == f)
+ return;
+
+ d->finishPlaying = f;
+ emit finishPlayingChanged(f);
+}
+
+/*!
+ \qmlproperty bool Animation::repeat
+ This property holds whether the animation should repeat.
+
+ If set, the animation will continuously repeat until it is explicitly
+ stopped - either by setting the \c running property to false, or by calling
+ the \c stop() method.
+
+ In the following example, the rectangle will spin indefinately.
+
+ \code
+ Rect {
+ rotation: NumericAnimation { running: true; repeat: true; from: 0 to: 360 }
+ }
+ \endcode
+*/
+bool QmlAbstractAnimation::repeat() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->repeat;
+}
+
+void QmlAbstractAnimation::setRepeat(bool r)
+{
+ Q_D(QmlAbstractAnimation);
+ if (r == d->repeat)
+ return;
+
+ d->repeat = r;
+ int lc = r ? -1 : 1;
+ qtAnimation()->setLoopCount(lc);
+ emit repeatChanged(r);
+}
+
+QmlAnimationGroup *QmlAbstractAnimation::group() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->group;
+}
+
+void QmlAbstractAnimation::setGroup(QmlAnimationGroup *g)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->group == g)
+ return;
+ if (d->group)
+ static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.removeAll(this);
+
+ d->group = g;
+
+ if (d->group && !static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.contains(this))
+ static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.append(this);
+
+ if (d->group)
+ ((QAnimationGroup*)d->group->qtAnimation())->addAnimation(qtAnimation());
+
+ //if (g) //if removed from a group, then the group should no longer be the parent
+ setParent(g);
+}
+
+/*!
+ \qmlproperty Object Animation::target
+ This property holds an explicit target object to animate.
+
+ The exact effect of the \c target property depends on how the animation
+ is being used. Refer to the \l animation documentation for details.
+*/
+QObject *QmlAbstractAnimation::target() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->target;
+}
+
+void QmlAbstractAnimation::setTarget(QObject *o)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->target == o)
+ return;
+
+ d->target = o;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = QmlMetaProperty(d->target, d->propertyName);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlproperty string Animation::property
+ This property holds an explicit property to animated.
+
+ The exact effect of the \c property property depends on how the animation
+ is being used. Refer to the \l animation documentation for details.
+*/
+QString QmlAbstractAnimation::property() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->propertyName;
+}
+
+void QmlAbstractAnimation::setProperty(const QString &n)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->propertyName == n)
+ return;
+
+ d->propertyName = n;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = QmlMetaProperty(d->target, d->propertyName);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlmethod Animation::start()
+ \brief Starts the animation.
+
+ If the animation is already running, calling this method has no effect. The
+ \c running property will be true following a call to \c start().
+*/
+void QmlAbstractAnimation::start()
+{
+ setRunning(true);
+}
+
+/*!
+ \qmlmethod Animation::stop()
+ \brief Stops the animation.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c stop().
+
+ Normally \c stop() stops the animation immediately, and the animation has
+ no further influence on property values. In this example animation
+ \code
+ Rect {
+ x: NumericAnimation { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ was stopped at time 250ms, the \c x property will have a value of 50.
+
+ However, if the \c finishPlaying property is set, the animation will
+ continue running until it completes and then stop. The \c running property
+ will still become false immediately.
+*/
+void QmlAbstractAnimation::stop()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlmethod Animation::restart()
+ \brief Restarts the animation.
+
+ This is a convenience method, and is equivalent to calling \c stop() and
+ then \c start().
+*/
+void QmlAbstractAnimation::restart()
+{
+ stop();
+ start();
+}
+
+/*!
+ \qmlmethod Animation::complete()
+ \brief Stops the animation, jumping to the final property values.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c complete().
+
+ Unlike \c stop(), \c complete() immediately fast-forwards the animation to
+ its end. In the following example,
+ \code
+ Rect {
+ x: NumericAnimation { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ calling \c stop() at time 250ms will result in the \c x property having
+ a value of 50, while calling \c complete() will set the \c x property to
+ 100, exactly as though the animation had played the whole way through.
+*/
+void QmlAbstractAnimation::complete()
+{
+ if (isRunning()) {
+ qtAnimation()->setCurrentTime(qtAnimation()->duration());
+ }
+}
+
+void QmlAbstractAnimation::setTarget(const QmlMetaProperty &p)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->userProperty.isNull)
+ d->userProperty = p;
+}
+
+//prepare is called before an animation begins
+//(when an animation is used as a simple animation, and not as part of a transition)
+void QmlAbstractAnimation::prepare(QmlMetaProperty &)
+{
+}
+
+void QmlAbstractAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_UNUSED(actions);
+ Q_UNUSED(modified);
+ Q_UNUSED(direction);
+}
+
+void QmlAbstractAnimation::timelineComplete()
+{
+ Q_D(QmlAbstractAnimation);
+ setRunning(false);
+ if (d->finishPlaying && d->repeat) {
+ qtAnimation()->setLoopCount(-1);
+ }
+}
+
+/*!
+ \qmlclass PauseAnimation QmlPauseAnimation
+ \inherits Animation
+ \brief The PauseAnimation provides a pause for an animation.
+
+ When used in a SequentialAnimation, PauseAnimation is a step when
+ nothing happens, for a specified duration.
+
+ A 500ms animation sequence, with a 100ms pause between two animations:
+ \code
+ SequentialAnimation {
+ NumericAnimation { ... duration: 200 }
+ PauseAnimation { duration: 100 }
+ NumericAnimation { ... duration: 200 }
+ }
+ \endcode
+*/
+/*!
+ \internal
+ \class QmlPauseAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlPauseAnimation class provides a pause for an animation.
+
+ When used in a QmlSequentialAnimation, QmlPauseAnimation is a step when
+ nothing happens, for a specified duration.
+
+ A QmlPauseAnimation object can be instantiated in Qml using the tag
+ \l{xmlPauseAnimation} {&lt;PauseAnimation&gt;}.
+*/
+
+QML_DEFINE_TYPE(QmlPauseAnimation,PauseAnimation)
+QmlPauseAnimation::QmlPauseAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlPauseAnimationPrivate), parent)
+{
+ Q_D(QmlPauseAnimation);
+ d->init();
+}
+
+QmlPauseAnimation::~QmlPauseAnimation()
+{
+}
+
+void QmlPauseAnimationPrivate::init()
+{
+ Q_Q(QmlPauseAnimation);
+ pa = new QPauseAnimation(q);
+}
+
+/*!
+ \qmlproperty int PauseAnimation::duration
+ This property holds the duration of the pause in milliseconds
+
+ The default value is 250.
+*/
+/*!
+ \property QmlPauseAnimation::duration
+ \brief the duration of the pause in milliseconds
+
+ The default value is 250.
+*/
+int QmlPauseAnimation::duration() const
+{
+ Q_D(const QmlPauseAnimation);
+ return d->pa->duration();
+}
+
+void QmlPauseAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlPauseAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlPauseAnimation);
+ if (d->pa->duration() == duration)
+ return;
+ d->pa->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+void QmlPauseAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlPauseAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+}
+
+QAbstractAnimation *QmlPauseAnimation::qtAnimation()
+{
+ Q_D(QmlPauseAnimation);
+ return d->pa;
+}
+
+/*!
+ \qmlclass ColorAnimation QmlColorAnimation
+ \inherits Animation
+ \brief The ColorAnimation allows you to animate color changes.
+
+ \code
+ ColorAnimation { from: "white"; to: "#c0c0c0"; duration: 100 }
+ \endcode
+
+ The default property animated is \c color, but like other animations,
+ this can be changed by setting \c property. The \c color property will
+ still animate. XXX is this a bug?
+*/
+/*!
+ \internal
+ \class QmlColorAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlColorAnimation class allows you to animate color changes.
+
+ A QmlColorAnimation object can be instantiated in Qml using the tag
+ \l{xmlColorAnimation} {&lt;ColorAnimation&gt;}.
+*/
+
+QmlColorAnimation::QmlColorAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlColorAnimationPrivate), parent)
+{
+ Q_D(QmlColorAnimation);
+ d->init();
+}
+
+QmlColorAnimation::~QmlColorAnimation()
+{
+}
+
+void QmlColorAnimationPrivate::init()
+{
+ Q_Q(QmlColorAnimation);
+ ca = new QmlTimeLineValueAnimator(q);
+ ca->setStartValue(QVariant(0.0f));
+ ca->setEndValue(QVariant(1.0f));
+}
+
+/*!
+ \qmlproperty int ColorAnimation::duration
+ This property holds the duration of the color transition, in milliseconds.
+
+ The default value is 250.
+*/
+/*!
+ \property QmlColorAnimation::duration
+ \brief the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+int QmlColorAnimation::duration() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->ca->duration();
+}
+
+void QmlColorAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlColorAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlColorAnimation);
+ if (d->ca->duration() == duration)
+ return;
+ d->ca->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty color ColorAnimation::from
+ This property holds the starting color.
+*/
+/*!
+ \property QmlColorAnimation::from
+ \brief the starting color.
+*/
+QColor QmlColorAnimation::from() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->fromValue;
+}
+
+void QmlColorAnimation::setFrom(const QColor &f)
+{
+ Q_D(QmlColorAnimation);
+ if (d->fromIsDefined && f == d->fromValue)
+ return;
+ d->fromValue = f;
+ d->fromIsDefined = f.isValid();
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty color ColorAnimation::from
+ This property holds the ending color.
+*/
+/*!
+ \property QmlColorAnimation::to
+ \brief the ending color.
+*/
+QColor QmlColorAnimation::to() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->toValue;
+}
+
+void QmlColorAnimation::setTo(const QColor &t)
+{
+ Q_D(QmlColorAnimation);
+ if (d->toIsDefined && t == d->toValue)
+ return;
+ d->toValue = t;
+ d->toIsDefined = t.isValid();
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty string ColorAnimation::easing
+ This property holds the easing curve used for the transition.
+
+ Each channel of the color is eased using the same easing curve.
+ See NumericAnimation::easing for a full discussion of easing,
+ and a list of available curves.
+*/
+QString QmlColorAnimation::easing() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->easing;
+}
+
+void QmlColorAnimation::setEasing(const QString &e)
+{
+ Q_D(QmlColorAnimation);
+ if (d->easing == e)
+ return;
+
+ d->easing = e;
+ d->ca->setEasingCurve(stringToCurve(d->easing));
+ emit easingChanged(e);
+}
+
+/*!
+ \qmlproperty list<Item> ColorAnimation::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlColorAnimation::filter()
+{
+ Q_D(QmlColorAnimation);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> ColorAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlColorAnimation::exclude()
+{
+ Q_D(QmlColorAnimation);
+ return &d->exclude;
+}
+
+void QmlColorAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlColorAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+ d->fromSourced = false;
+ d->value.QmlTimeLineValue::setValue(0.);
+ d->ca->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->ca->setFromSourcedValue(&d->fromSourced);
+}
+
+QAbstractAnimation *QmlColorAnimation::qtAnimation()
+{
+ Q_D(QmlColorAnimation);
+ return d->ca;
+}
+
+void QmlColorAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlColorAnimation);
+ Q_UNUSED(direction);
+
+ struct NTransitionData : public QmlTimeLineValue
+ {
+ QmlStateActions actions;
+ void write(QmlMetaProperty &property, const QVariant &color)
+ {
+ if (property.propertyType() == QVariant::Color) {
+ property.write(color);
+ }
+ }
+
+ void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QColor to(action.toValue.value<QColor>());
+
+ if (v == 1.) {
+ write(action.property, to);
+ } else {
+ if (action.fromValue.isNull()) {
+ action.fromValue = action.property.read();
+ if (action.fromValue.isNull())
+ action.fromValue = QVariant(QColor());
+ }
+
+ QColor from(action.fromValue.value<QColor>());
+
+ QVariant newColor = QmlColorAnimationPrivate::colorInterpolator(&from, &to, v);
+ write(action.property, newColor);
+ }
+ }
+ }
+ };
+
+ //XXX should we get rid of this?
+ QStringList props;
+ props << QLatin1String("color");
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ NTransitionData *data = new NTransitionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ if (d->fromIsDefined) {
+ myAction.fromValue = QVariant(d->fromValue);
+ } else {
+ myAction.fromValue = QVariant();
+ }
+ if (d->toIsDefined)
+ myAction.toValue = QVariant(d->toValue);
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->toValue.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+
+ if (d->fromIsDefined)
+ myAction.fromValue = QVariant(d->fromValue);
+
+ myAction.toValue = QVariant(d->toValue);
+ myAction.bv = 0;
+ myAction.event = 0;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count())
+ d->ca->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ else
+ delete data;
+}
+
+QVariantAnimation::Interpolator QmlColorAnimationPrivate::colorInterpolator = 0;
+
+void QmlColorAnimationPrivate::valueChanged(qreal v)
+{
+ if (!fromSourced) {
+ if (!fromIsDefined) {
+ fromValue = qvariant_cast<QColor>(property.read());
+ }
+ fromSourced = true;
+ }
+
+ if (property.propertyType() == QVariant::Color) {
+ QVariant newColor = colorInterpolator(&fromValue, &toValue, v);
+ property.write(newColor);
+ }
+}
+QML_DEFINE_TYPE(QmlColorAnimation,ColorAnimation)
+
+/*!
+ \qmlclass RunScriptAction QmlRunScriptAction
+ \inherits Animation
+ \brief The RunScripAction allows scripts to be run during transitions.
+
+*/
+/*!
+ \internal
+ \class QmlRunScriptAction
+ \brief The QmlRunScriptAction class allows scripts to be run during transitions
+
+ \sa xmlRunScriptAction
+*/
+QmlRunScriptAction::QmlRunScriptAction(QObject *parent)
+ :QmlAbstractAnimation(*(new QmlRunScriptActionPrivate), parent)
+{
+ Q_D(QmlRunScriptAction);
+ d->init();
+}
+
+QmlRunScriptAction::~QmlRunScriptAction()
+{
+}
+
+void QmlRunScriptActionPrivate::init()
+{
+ Q_Q(QmlRunScriptAction);
+ rsa = new QActionAnimation(&proxy, q);
+}
+
+/*!
+ \qmlproperty QString RunScript::script
+ This property holds the script to run.
+*/
+QString QmlRunScriptAction::script() const
+{
+ Q_D(const QmlRunScriptAction);
+ return d->script;
+}
+
+void QmlRunScriptAction::setScript(const QString &script)
+{
+ Q_D(QmlRunScriptAction);
+ if (script == d->script)
+ return;
+ d->script = script;
+ emit scriptChanged(script);
+}
+
+/*!
+ \qmlproperty QString RunScript::script
+ This property holds the file containing the script to run.
+*/
+QString QmlRunScriptAction::file() const
+{
+ Q_D(const QmlRunScriptAction);
+ return d->file;
+}
+
+void QmlRunScriptAction::setFile(const QString &file)
+{
+ Q_D(QmlRunScriptAction);
+ if (file == d->file)
+ return;
+ d->file = file;
+ emit fileChanged(file);
+}
+
+void QmlRunScriptActionPrivate::execute()
+{
+ Q_Q(QmlRunScriptAction);
+ QString scriptStr = script;
+ if (!file.isEmpty()){
+ QFile scriptFile(file);
+ if (scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)){
+ scriptStr = QString::fromUtf8(scriptFile.readAll());
+ }
+ }
+
+ if (!scriptStr.isEmpty()) {
+ QmlExpression expr(qmlContext(q), scriptStr, q);
+ expr.setTrackChange(false);
+ expr.value();
+ }
+}
+
+QAbstractAnimation *QmlRunScriptAction::qtAnimation()
+{
+ Q_D(QmlRunScriptAction);
+ return d->rsa;
+}
+
+QML_DEFINE_TYPE(QmlRunScriptAction, RunScriptAction)
+
+/*!
+ \qmlclass SetPropertyAction QmlSetPropertyAction
+ \inherits Animation
+ \brief The SetPropertyAction allows property changes during transitions.
+
+ Explicitly set \c theimage.smooth=true during a transition:
+ \code
+ SetPropertyAction { target: theimage; property: "smooth"; value: true }
+ \endcode
+
+ Set \c thewebview.url to the value set for the destination state:
+ \code
+ SetPropertyAction { target: thewebview; property: "url" }
+ \endcode
+
+ The SetPropertyAction is immediate -
+ the target property is not animated to the selected value in any way.
+*/
+/*!
+ \internal
+ \class QmlSetPropertyAction
+ \brief The QmlSetPropertyAction class allows property changes during transitions.
+
+ A QmlSetPropertyAction object can be instantiated in Qml using the tag
+ \l{xmlSetPropertyAction} {&lt;SetPropertyAction&gt;}.
+*/
+QmlSetPropertyAction::QmlSetPropertyAction(QObject *parent)
+: QmlAbstractAnimation(*(new QmlSetPropertyActionPrivate), parent)
+{
+ Q_D(QmlSetPropertyAction);
+ d->init();
+}
+
+QmlSetPropertyAction::~QmlSetPropertyAction()
+{
+}
+
+void QmlSetPropertyActionPrivate::init()
+{
+ Q_Q(QmlSetPropertyAction);
+ spa = new QActionAnimation(q);
+}
+
+/*!
+ \qmlproperty string SetPropertyAction::properties
+ This property holds the properties to be immediately set, comma-separated.
+*/
+QString QmlSetPropertyAction::properties() const
+{
+ Q_D(const QmlSetPropertyAction);
+ return d->properties;
+}
+
+void QmlSetPropertyAction::setProperties(const QString &p)
+{
+ Q_D(QmlSetPropertyAction);
+ if (d->properties == p)
+ return;
+ d->properties = p;
+ emit propertiesChanged(p);
+}
+
+/*!
+ \qmlproperty list<Item> SetPropertyAction::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlSetPropertyAction::filter()
+{
+ Q_D(QmlSetPropertyAction);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> SetPropertyAction::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlSetPropertyAction::exclude()
+{
+ Q_D(QmlSetPropertyAction);
+ return &d->exclude;
+}
+
+/*!
+ \qmlproperty any SetPropertyAction::value
+ This property holds the value to be set on the property.
+ If not set, then the value defined for the end state of the transition.
+*/
+QVariant QmlSetPropertyAction::value() const
+{
+ Q_D(const QmlSetPropertyAction);
+ return d->value;
+}
+
+void QmlSetPropertyAction::setValue(const QVariant &v)
+{
+ Q_D(QmlSetPropertyAction);
+ if (d->value.isNull || d->value != v) {
+ d->value = v;
+ emit valueChanged(v);
+ }
+}
+
+void QmlSetPropertyActionPrivate::doAction()
+{
+ property.write(value);
+}
+
+QAbstractAnimation *QmlSetPropertyAction::qtAnimation()
+{
+ Q_D(QmlSetPropertyAction);
+ return d->spa;
+}
+
+void QmlSetPropertyAction::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlSetPropertyAction);
+
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ d->spa->setAnimAction(&d->proxy, QAbstractAnimation::KeepWhenStopped);
+}
+
+void QmlSetPropertyAction::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlSetPropertyAction);
+ Q_UNUSED(direction);
+
+ struct QmlSetPropertyAnimationAction : public QAbstractAnimationAction
+ {
+ QmlStateActions actions;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const Action &action = actions.at(ii);
+ QmlBehaviour::_ignore = true;
+ action.property.write(action.toValue);
+ QmlBehaviour::_ignore = false;
+ }
+ }
+ };
+
+ QStringList props = d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ if (d->value.isValid())
+ myAction.toValue = d->value;
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->value.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+ myAction.toValue = d->value;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count()) {
+ d->spa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(QmlSetPropertyAction,SetPropertyAction)
+
+/*!
+ \qmlclass ParentChangeAction QmlParentChangeAction
+ \inherits Animation
+ \brief The ParentChangeAction allows parent changes during transitions.
+
+ The ParentChangeAction is immediate - it is not animated in any way.
+*/
+
+QmlParentChangeAction::QmlParentChangeAction(QObject *parent)
+: QmlAbstractAnimation(*(new QmlParentChangeActionPrivate), parent)
+{
+ Q_D(QmlParentChangeAction);
+ d->init();
+}
+
+QmlParentChangeAction::~QmlParentChangeAction()
+{
+}
+
+void QmlParentChangeActionPrivate::init()
+{
+ Q_Q(QmlParentChangeAction);
+ cpa = new QActionAnimation(q);
+}
+
+void QmlParentChangeActionPrivate::doAction()
+{
+ //XXX property.write(value);
+}
+
+void QmlParentChangeAction::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlParentChangeAction);
+
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ //XXX
+}
+
+QAbstractAnimation *QmlParentChangeAction::qtAnimation()
+{
+ Q_D(QmlParentChangeAction);
+ return d->cpa;
+}
+
+void QmlParentChangeAction::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlParentChangeAction);
+ Q_UNUSED(direction);
+
+ struct QmlParentChangeActionData : public QAbstractAnimationAction
+ {
+ QmlStateActions actions;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const Action &action = actions.at(ii);
+ QmlBehaviour::_ignore = true;
+ action.property.write(action.toValue);
+ QmlBehaviour::_ignore = false;
+ }
+ }
+ };
+
+ QmlParentChangeActionData *data = new QmlParentChangeActionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((!target() || target() == obj) && propertyName == QString(QLatin1String("moveToParent"))) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ /*if (d->value.isValid())
+ myAction.toValue = d->value;*/
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ /*if (d->value.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+ myAction.toValue = d->value;
+ data->actions << myAction;
+ }
+ }*/
+
+ if (data->actions.count()) {
+ d->cpa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(QmlParentChangeAction,ParentChangeAction)
+
+/*!
+ \qmlclass NumericAnimation QmlNumericAnimation
+ \inherits Animation
+ \brief The NumericAnimation allows you to animate changes in properties of type qreal.
+
+ Animate a set of properties over 200ms, from their values in the start state to
+ their values in the end state of the transition:
+ \code
+ NumericAnimation { properties: "x,y,scale"; duration: 200 }
+ \endcode
+*/
+
+/*!
+ \internal
+ \class QmlNumericAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlNumericAnimation class allows you to animate changes in properties of type qreal.
+
+ A QmlNumericAnimation object can be instantiated in Qml using the tag
+ \l{xmlNumericAnimation} {&lt;NumericAnimation&gt;}.
+*/
+
+QmlNumericAnimation::QmlNumericAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlNumericAnimationPrivate), parent)
+{
+ Q_D(QmlNumericAnimation);
+ d->init();
+}
+
+QmlNumericAnimation::~QmlNumericAnimation()
+{
+}
+
+void QmlNumericAnimationPrivate::init()
+{
+ Q_Q(QmlNumericAnimation);
+ na = new QmlTimeLineValueAnimator(q);
+ na->setStartValue(QVariant(0.0f));
+ na->setEndValue(QVariant(1.0f));
+}
+
+/*!
+ \qmlproperty int NumericAnimation::duration
+ This property holds the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+/*!
+ \property QmlNumericAnimation::duration
+ \brief the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+int QmlNumericAnimation::duration() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->na->duration();
+}
+
+void QmlNumericAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlNumericAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlNumericAnimation);
+ if (d->na->duration() == duration)
+ return;
+ d->na->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty real NumericAnimation::from
+ This property holds the starting value.
+ If not set, then the value defined in the start state of the transition.
+*/
+/*!
+ \property QmlNumericAnimation::from
+ \brief the starting value.
+*/
+qreal QmlNumericAnimation::from() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->from;
+}
+
+void QmlNumericAnimation::setFrom(qreal f)
+{
+ Q_D(QmlNumericAnimation);
+ if (!d->from.isNull && f == d->from)
+ return;
+ d->from = f;
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty real NumericAnimation::to
+ This property holds the ending value.
+ If not set, then the value defined in the end state of the transition.
+*/
+/*!
+ \property QmlNumericAnimation::to
+ \brief the ending value.
+*/
+qreal QmlNumericAnimation::to() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->to;
+}
+
+void QmlNumericAnimation::setTo(qreal t)
+{
+ Q_D(QmlNumericAnimation);
+ if (!d->to.isNull && t == d->to)
+ return;
+ d->to = t;
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty string NumericAnimation::easing
+ \brief the easing curve used for the transition.
+
+ Available values are:
+
+ \list
+ \i \e easeNone - Easing equation function for a simple linear tweening, with no easing.
+ \i \e easeInQuad - Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
+ \i \e easeOutQuad - Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
+ \i \e easeInOutQuad - Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuad - Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInCubic - Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
+ \i \e easeOutCubic - Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity.
+ \i \e easeInOutCubic - Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInCubic - Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInQuart - Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
+ \i \e easeOutQuart - Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity.
+ \i \e easeInOutQuart - Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuart - Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInQuint - Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
+ \i \e easeOutQuint - Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity.
+ \i \e easeInOutQuint - Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuint - Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInSine - Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
+ \i \e easeOutSine - Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity.
+ \i \e easeInOutSine - Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInSine - Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInExpo - Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
+ \i \e easeOutExpo - Easing equation function for an exponential (2^t) easing out: decelerating from zero velocity.
+ \i \e easeInOutExpo - Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInExpo - Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInCirc - Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
+ \i \e easeOutCirc - Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating from zero velocity.
+ \i \e easeInOutCirc - Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInCirc - Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \i \e easeOutElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \i \e easeInOutElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ \i \e easeOutBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating from zero velocity.
+ \i \e easeInOutBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeOutBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity.
+ \i \e easeInBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
+ \i \e easeInOutBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
+ \endlist
+*/
+
+/*!
+ \property QmlNumericAnimation::easing
+ This property holds the easing curve to use.
+
+ \sa QEasingCurve
+*/
+QString QmlNumericAnimation::easing() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->easing;
+}
+
+void QmlNumericAnimation::setEasing(const QString &e)
+{
+ Q_D(QmlNumericAnimation);
+ if (d->easing == e)
+ return;
+
+ d->easing = e;
+ d->na->setEasingCurve(stringToCurve(d->easing));
+ emit easingChanged(e);
+}
+
+/*!
+ \qmlproperty string NumericAnimation::properties
+ This property holds the properties this animation should be applied to.
+
+ This is a comma-separated list of properties that should use
+ this animation when they change.
+*/
+/*!
+ \property QmlNumericAnimation::properties
+ \brief the properties this animation should be applied to.
+
+ properties holds a comma-separated list of properties that should use
+ this animation when they change.
+*/
+QString QmlNumericAnimation::properties() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->properties;
+}
+
+void QmlNumericAnimation::setProperties(const QString &prop)
+{
+ Q_D(QmlNumericAnimation);
+ if (d->properties == prop)
+ return;
+
+ d->properties = prop;
+ emit propertiesChanged(prop);
+}
+
+/*!
+ \qmlproperty list<Item> NumericAnimation::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlNumericAnimation::filter()
+{
+ Q_D(QmlNumericAnimation);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> NumericAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlNumericAnimation::exclude()
+{
+ Q_D(QmlNumericAnimation);
+ return &d->exclude;
+}
+
+void QmlNumericAnimationPrivate::valueChanged(qreal r)
+{
+ if (!fromSourced) {
+ if (from.isNull) {
+ fromValue = qvariant_cast<qreal>(property.read());
+ } else {
+ fromValue = from;
+ }
+ fromSourced = true;
+ }
+
+ if (r == 1.) {
+ property.write(to.value);
+ } else {
+ qreal val = fromValue + (to-fromValue) * r;
+ property.write(val);
+ }
+}
+
+void QmlNumericAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlNumericAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+ d->fromSourced = false;
+ d->value.QmlTimeLineValue::setValue(0.);
+ d->na->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->na->setFromSourcedValue(&d->fromSourced);
+}
+
+QAbstractAnimation *QmlNumericAnimation::qtAnimation()
+{
+ Q_D(QmlNumericAnimation);
+ return d->na;
+}
+
+void QmlNumericAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlNumericAnimation);
+ Q_UNUSED(direction);
+
+ struct NTransitionData : public QmlTimeLineValue
+ {
+ QmlStateActions actions;
+ void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QmlBehaviour::_ignore = true;
+ if (v == 1.)
+ action.property.write(action.toValue.toDouble());
+ else {
+ if (action.fromValue.isNull()) {
+ action.fromValue = action.property.read();
+ if (action.fromValue.isNull()) {
+ action.fromValue = QVariant(0.);
+ }
+ }
+ qreal start = action.fromValue.toDouble();
+ qreal end = action.toValue.toDouble();
+ qreal val = start + (end-start) * v;
+ action.property.write(val);
+ }
+ QmlBehaviour::_ignore = false;
+ }
+ }
+ };
+
+ QStringList props = d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ NTransitionData *data = new NTransitionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+ if (d->from.isValid()) {
+ myAction.fromValue = QVariant(d->from);
+ } else {
+ myAction.fromValue = QVariant();
+ }
+ if (d->to.isValid())
+ myAction.toValue = QVariant(d->to);
+
+ modified << action.property;
+
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->to.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+
+ if (d->from.isValid())
+ myAction.fromValue = QVariant(d->from);
+
+ myAction.toValue = QVariant(d->to);
+ myAction.bv = 0;
+ myAction.event = 0;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count()) {
+ d->na->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(QmlNumericAnimation,NumericAnimation)
+
+QmlAnimationGroup::QmlAnimationGroup(QObject *parent)
+: QmlAbstractAnimation(*(new QmlAnimationGroupPrivate), parent)
+{
+}
+
+QmlAnimationGroup::~QmlAnimationGroup()
+{
+}
+
+QmlList<QmlAbstractAnimation *> *QmlAnimationGroup::animations()
+{
+ Q_D(QmlAnimationGroup);
+ return &d->animations;
+}
+
+/*!
+ \qmlclass SequentialAnimation QmlSequentialAnimation
+ \inherits Animation
+ \brief The SequentialAnimation allows you to run animations sequentially.
+
+ Animations controlled in SequentialAnimation will be run one after the other.
+
+ The following example chains two numeric animations together. The \c MyItem
+ object will animate from its current x position to 100, and then back to 0.
+
+ \code
+ SequentialAnimation {
+ NumericAnimation { target: MyItem; property: "x"; to: 100 }
+ NumericAnimation { target: MyItem; property: "x"; to: 0 }
+ }
+ \endcode
+
+ \sa ParallelAnimation
+*/
+
+QmlSequentialAnimation::QmlSequentialAnimation(QObject *parent) :
+ QmlAnimationGroup(parent)
+{
+ Q_D(QmlAnimationGroup);
+ d->ag = new QSequentialAnimationGroup(this);
+}
+
+QmlSequentialAnimation::~QmlSequentialAnimation()
+{
+}
+
+void QmlSequentialAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlAnimationGroup);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->prepare(d->property);
+}
+
+QAbstractAnimation *QmlSequentialAnimation::qtAnimation()
+{
+ Q_D(QmlAnimationGroup);
+ return d->ag;
+}
+
+void QmlSequentialAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlAnimationGroup);
+
+ int inc = 1;
+ int from = 0;
+ if (direction == Backward) {
+ inc = -1;
+ from = d->animations.count() - 1;
+ }
+
+ //XXX removing and readding isn't ideal; we do it to get around the problem mentioned below.
+ for (int i = d->ag->animationCount()-1; i >= 0; --i)
+ d->ag->takeAnimationAt(i);
+
+ for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) {
+ d->animations.at(ii)->transition(actions, modified, direction);
+ d->ag->addAnimation(d->animations.at(ii)->qtAnimation());
+ }
+
+ //XXX changing direction means all the animations play in reverse, while we only want the ordering reversed.
+ //d->ag->setDirection(direction == Backward ? QAbstractAnimation::Backward : QAbstractAnimation::Forward);
+}
+
+QML_DEFINE_TYPE(QmlSequentialAnimation,SequentialAnimation)
+
+/*!
+ \qmlclass ParallelAnimation QmlParallelAnimation
+ \inherits Animation
+ \brief The ParallelAnimation allows you to run animations in parallel.
+
+ Animations contained in ParallelAnimation will be run at the same time.
+
+ The following animation demonstrates animating the \c MyItem item
+ to (100,100) by animating the x and y properties in parallel.
+
+ \code
+ ParallelAnimation {
+ NumericAnimation { target: MyItem; property: "x"; to: 100 }
+ NumericAnimation { target: MyItem; property: "y"; to: 100 }
+ }
+ \endcode
+
+ \sa SequentialAnimation
+*/
+/*!
+ \internal
+ \class QmlParallelAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlParallelAnimation class allows you to run animations in parallel.
+
+ Animations controlled by QmlParallelAnimation will be run at the same time.
+
+ \sa QmlSequentialAnimation
+
+ A QmlParallelAnimation object can be instantiated in Qml using the tag
+ \l{xmlParallelAnimation} {&lt;ParallelAnimation&gt;}.
+*/
+
+QmlParallelAnimation::QmlParallelAnimation(QObject *parent) :
+ QmlAnimationGroup(parent)
+{
+ Q_D(QmlAnimationGroup);
+ d->ag = new QParallelAnimationGroup(this);
+}
+
+QmlParallelAnimation::~QmlParallelAnimation()
+{
+}
+
+void QmlParallelAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlAnimationGroup);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->prepare(d->property);
+}
+
+QAbstractAnimation *QmlParallelAnimation::qtAnimation()
+{
+ Q_D(QmlAnimationGroup);
+ return d->ag;
+}
+
+void QmlParallelAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlAnimationGroup);
+
+ for (int ii = 0; ii < d->animations.count(); ++ii) {
+ d->animations.at(ii)->transition(actions, modified, direction);
+ }
+}
+
+QML_DEFINE_TYPE(QmlParallelAnimation,ParallelAnimation)
+
+QVariant QmlVariantAnimationPrivate::interpolateVariant(const QVariant &from, const QVariant &to, qreal progress)
+{
+ if (from.userType() != to.userType())
+ return QVariant();
+
+ QVariantAnimation::Interpolator interpolator = QVariantAnimationPrivate::getInterpolator(from.userType());
+ return interpolator(from.constData(), to.constData(), progress);
+}
+
+//convert a variant from string type to another animatable type
+void QmlVariantAnimationPrivate::convertVariant(QVariant &variant, QVariant::Type type)
+{
+ if (variant.type() != QVariant::String) {
+ variant.convert(type);
+ return;
+ }
+
+ switch (type) {
+ case QVariant::Rect: {
+ variant.setValue(QmlStringConverters::rectFFromString(variant.toString()).toRect());
+ break;
+ }
+ case QVariant::RectF: {
+ variant.setValue(QmlStringConverters::rectFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Point: {
+ variant.setValue(QmlStringConverters::pointFFromString(variant.toString()).toPoint());
+ break;
+ }
+ case QVariant::PointF: {
+ variant.setValue(QmlStringConverters::pointFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Size: {
+ variant.setValue(QmlStringConverters::sizeFFromString(variant.toString()).toSize());
+ break;
+ }
+ case QVariant::SizeF: {
+ variant.setValue(QmlStringConverters::sizeFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Color: {
+ variant.setValue(QmlStringConverters::colorFromString(variant.toString()));
+ break;
+ }
+ default:
+ variant.convert(type);
+ break;
+ }
+}
+
+/*!
+ \qmlclass VariantAnimation QmlVariantAnimation
+ \inherits Animation
+ \brief The VariantAnimation allows you to animate changes in properties of type QVariant.
+
+ Animate a size property over 200ms, from its current size to 20-by-20:
+ \code
+ VariantAnimation { property: "size"; to: "20x20"; duration: 200 }
+ \endcode
+*/
+
+QmlVariantAnimation::QmlVariantAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlVariantAnimationPrivate), parent)
+{
+ Q_D(QmlVariantAnimation);
+ d->init();
+}
+
+QmlVariantAnimation::~QmlVariantAnimation()
+{
+}
+
+void QmlVariantAnimationPrivate::init()
+{
+ Q_Q(QmlVariantAnimation);
+ va = new QmlTimeLineValueAnimator(q);
+ va->setStartValue(QVariant(0.0f));
+ va->setEndValue(QVariant(1.0f));
+}
+
+/*!
+ \qmlproperty int VariantAnimation::duration
+ This property holds the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+/*!
+ \property QmlVariantAnimation::duration
+ \brief the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+int QmlVariantAnimation::duration() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->va->duration();
+}
+
+void QmlVariantAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlVariantAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlVariantAnimation);
+ if (d->va->duration() == duration)
+ return;
+ d->va->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty real VariantAnimation::from
+ This property holds the starting value.
+ If not set, then the value defined in the start state of the transition.
+*/
+/*!
+ \property QmlVariantAnimation::from
+ \brief the starting value.
+*/
+QVariant QmlVariantAnimation::from() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->from;
+}
+
+void QmlVariantAnimation::setFrom(const QVariant &f)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->fromIsDefined && f == d->from)
+ return;
+ d->from = f;
+ d->fromIsDefined = f.isValid();
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty real VariantAnimation::to
+ This property holds the ending value.
+ If not set, then the value defined in the end state of the transition.
+*/
+/*!
+ \property QmlVariantAnimation::to
+ \brief the ending value.
+*/
+QVariant QmlVariantAnimation::to() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->to;
+}
+
+void QmlVariantAnimation::setTo(const QVariant &t)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->toIsDefined && t == d->to)
+ return;
+ d->to = t;
+ d->toIsDefined = t.isValid();
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty string VariantAnimation::easing
+ This property holds the easing curve used for the transition.
+
+ See NumericAnimation::easing for a full discussion of easing,
+ and a list of available curves.
+*/
+
+/*!
+ \property QmlVariantAnimation::easing
+ \brief the easing curve to use.
+
+ \sa QEasingCurve
+*/
+QString QmlVariantAnimation::easing() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->easing;
+}
+
+void QmlVariantAnimation::setEasing(const QString &e)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->easing == e)
+ return;
+
+ d->easing = e;
+ d->va->setEasingCurve(stringToCurve(d->easing));
+ emit easingChanged(e);
+}
+
+/*!
+ \qmlproperty string VariantAnimation::properties
+ This property holds the properties this animation should be applied to.
+
+ This is a comma-separated list of properties that should use
+ this animation when they change.
+*/
+/*!
+ \property QmlVariantAnimation::properties
+ \brief the properties this animation should be applied to
+
+ properties holds a copy separated list of properties that should use
+ this animation when they change.
+*/
+QString QmlVariantAnimation::properties() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->properties;
+}
+
+void QmlVariantAnimation::setProperties(const QString &prop)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->properties == prop)
+ return;
+
+ d->properties = prop;
+ emit propertiesChanged(prop);
+}
+
+/*!
+ \qmlproperty list<Item> VariantAnimation::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlVariantAnimation::filter()
+{
+ Q_D(QmlVariantAnimation);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> VariantAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlVariantAnimation::exclude()
+{
+ Q_D(QmlVariantAnimation);
+ return &d->exclude;
+}
+
+void QmlVariantAnimationPrivate::valueChanged(qreal r)
+{
+ if (!fromSourced) {
+ if (!fromIsDefined) {
+ from = property.read();
+ }
+ fromSourced = true;
+ }
+
+ if (r == 1.) {
+ property.write(to);
+ } else {
+ QVariant val = interpolateVariant(from, to, r);
+ property.write(val);
+ }
+}
+
+QAbstractAnimation *QmlVariantAnimation::qtAnimation()
+{
+ Q_D(QmlVariantAnimation);
+ return d->va;
+}
+
+void QmlVariantAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ d->convertVariant(d->to, (QVariant::Type)d->property.propertyType());
+ if (d->fromIsDefined)
+ d->convertVariant(d->from, (QVariant::Type)d->property.propertyType());
+
+ d->fromSourced = false;
+ d->value.QmlTimeLineValue::setValue(0.);
+ d->va->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->va->setFromSourcedValue(&d->fromSourced);
+}
+
+void QmlVariantAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlVariantAnimation);
+ Q_UNUSED(direction);
+
+ struct NTransitionData : public QmlTimeLineValue
+ {
+ QmlStateActions actions;
+ void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ if (v == 1.)
+ action.property.write(action.toValue);
+ else {
+ if (action.fromValue.isNull()) {
+ action.fromValue = action.property.read();
+ /*if (action.fromValue.isNull())
+ action.fromValue = QVariant(0.);*/ //XXX can we give a default value for any type?
+ }
+ QVariant val = QmlVariantAnimationPrivate::interpolateVariant(action.fromValue, action.toValue, v);
+ action.property.write(val);
+ }
+ }
+ }
+ };
+
+ QStringList props = d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ NTransitionData *data = new NTransitionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ if (d->fromIsDefined) {
+ myAction.fromValue = d->from;
+ } else {
+ myAction.fromValue = QVariant();
+ }
+ if (d->toIsDefined)
+ myAction.toValue = d->to;
+
+ d->convertVariant(myAction.fromValue, (QVariant::Type)myAction.property.propertyType());
+ d->convertVariant(myAction.toValue, (QVariant::Type)myAction.property.propertyType());
+
+ modified << action.property;
+
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->toIsDefined && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+
+ if (d->fromIsDefined) {
+ d->convertVariant(d->from, (QVariant::Type)myAction.property.propertyType());
+ myAction.fromValue = d->from;
+ }
+
+ d->convertVariant(d->to, (QVariant::Type)myAction.property.propertyType());
+ myAction.toValue = d->to;
+ myAction.bv = 0;
+ myAction.event = 0;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count()) {
+ d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+//XXX whats the best name for this? (just Animation?)
+QML_DEFINE_TYPE(QmlVariantAnimation,VariantAnimation)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlanimation.h b/src/declarative/util/qmlanimation.h
new file mode 100644
index 0000000..8b9ecc2
--- /dev/null
+++ b/src/declarative/util/qmlanimation.h
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLANIMATION_H
+#define QMLANIMATION_H
+
+#include <QtCore/qvariant.h>
+#include <QtCore/QAbstractAnimation>
+#include <QtGui/qcolor.h>
+#include <QtDeclarative/qmltransition.h>
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlstate.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractAnimationPrivate;
+class QmlAnimationGroup;
+class QmlAbstractAnimation : public QmlPropertyValueSource, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAbstractAnimation)
+
+ Q_INTERFACES(QmlParserStatus)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool finishPlaying READ finishPlaying WRITE setFinishPlaying NOTIFY finishPlayingChanged())
+ Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged)
+ Q_CLASSINFO("DefaultMethod", "start()")
+ Q_INTERFACES(QmlParserStatus)
+
+public:
+ QmlAbstractAnimation(QObject *parent=0);
+ virtual ~QmlAbstractAnimation();
+
+ bool isRunning() const;
+ void setRunning(bool);
+ bool finishPlaying() const;
+ void setFinishPlaying(bool);
+ bool repeat() const;
+ void setRepeat(bool);
+
+ QmlAnimationGroup *group() const;
+ void setGroup(QmlAnimationGroup *);
+
+ QObject *target() const;
+ void setTarget(QObject *);
+ QString property() const;
+ void setProperty(const QString &);
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void started();
+ void completed();
+ void runningChanged(bool);
+ void repeatChanged(bool);
+ void targetChanged(QObject *, const QString &);
+ void finishPlayingChanged(bool);
+
+public Q_SLOTS:
+ void restart();
+ void start();
+ void stop();
+ void complete();
+
+protected:
+ virtual void setTarget(const QmlMetaProperty &);
+ QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent);
+
+public:
+ enum TransitionDirection { Forward, Backward };
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual void prepare(QmlMetaProperty &);
+ virtual QAbstractAnimation *qtAnimation() = 0;
+
+private Q_SLOTS:
+ void timelineComplete();
+};
+
+QML_DECLARE_TYPE(QmlAbstractAnimation)
+
+class QmlPauseAnimationPrivate;
+class QmlPauseAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPauseAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+
+public:
+ QmlPauseAnimation(QObject *parent=0);
+ virtual ~QmlPauseAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+Q_SIGNALS:
+ void durationChanged(int);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlPauseAnimation)
+
+class QmlColorAnimationPrivate;
+class QmlColorAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlColorAnimation)
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QColor from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(QColor to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QList<QObject *>* filter READ filter)
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude)
+
+public:
+ QmlColorAnimation(QObject *parent=0);
+ virtual ~QmlColorAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+ QColor from() const;
+ void setFrom(const QColor &);
+
+ QColor to() const;
+ void setTo(const QColor &);
+
+ QString easing() const;
+ void setEasing(const QString &);
+
+ QList<QObject *> *filter();
+
+ QList<QObject *> *exclude();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(const QColor &);
+ void toChanged(const QColor &);
+ void easingChanged(const QString &);
+};
+QML_DECLARE_TYPE(QmlColorAnimation)
+
+class QmlRunScriptActionPrivate;
+class QmlRunScriptAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlRunScriptAction)
+
+ Q_PROPERTY(QString script READ script WRITE setScript NOTIFY scriptChanged)
+ Q_PROPERTY(QString file READ file WRITE setFile NOTIFY fileChanged)
+
+public:
+ QmlRunScriptAction(QObject *parent=0);
+ virtual ~QmlRunScriptAction();
+
+ QString script() const;
+ void setScript(const QString &);
+
+ QString file() const;
+ void setFile(const QString &);
+
+Q_SIGNALS:
+ void fileChanged(const QString &);
+ void scriptChanged(const QString &);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+};
+QML_DECLARE_TYPE(QmlRunScriptAction)
+
+class QmlSetPropertyActionPrivate;
+class QmlSetPropertyAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlSetPropertyAction)
+
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QList<QObject *>* filter READ filter)
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ QmlSetPropertyAction(QObject *parent=0);
+ virtual ~QmlSetPropertyAction();
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *filter();
+ QList<QObject *> *exclude();
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &);
+ void propertiesChanged(const QString &);
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlSetPropertyAction)
+
+class QmlParentChangeActionPrivate;
+class QmlParentChangeAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlParentChangeAction)
+
+ //XXX should have parent property as well for when it isn't part of a transition
+
+public:
+ QmlParentChangeAction(QObject *parent=0);
+ virtual ~QmlParentChangeAction();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlParentChangeAction)
+
+class QmlNumericAnimationPrivate;
+class QmlNumericAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlNumericAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QList<QObject *>* filter READ filter)
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude)
+
+public:
+ QmlNumericAnimation(QObject *parent=0);
+ virtual ~QmlNumericAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+ qreal from() const;
+ void setFrom(qreal);
+
+ qreal to() const;
+ void setTo(qreal);
+
+ QString easing() const;
+ void setEasing(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *filter();
+ QList<QObject *> *exclude();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(qreal);
+ void toChanged(qreal);
+ void easingChanged(const QString &);
+ void propertiesChanged(const QString &);
+};
+QML_DECLARE_TYPE(QmlNumericAnimation)
+
+#if 0
+class QmlDiscreteAnimation : public QmlAbstractAnimation
+{
+Q_OBJECT
+};
+#endif
+
+class QmlAnimationGroupPrivate;
+class QmlAnimationGroup : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup)
+
+ Q_CLASSINFO("DefaultProperty", "animations")
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *> *animations READ animations)
+
+public:
+ QmlAnimationGroup(QObject *parent);
+ virtual ~QmlAnimationGroup();
+
+ QmlList<QmlAbstractAnimation *>* animations();
+};
+
+class QmlSequentialAnimation : public QmlAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup)
+
+public:
+ QmlSequentialAnimation(QObject *parent=0);
+ virtual ~QmlSequentialAnimation();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlSequentialAnimation)
+
+class QmlParallelAnimation : public QmlAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup)
+
+public:
+ QmlParallelAnimation(QObject *parent=0);
+ virtual ~QmlParallelAnimation();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlParallelAnimation)
+
+class QmlVariantAnimationPrivate;
+class QmlVariantAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlVariantAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QVariant from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(QVariant to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QList<QObject *>* filter READ filter)
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude)
+
+public:
+ QmlVariantAnimation(QObject *parent=0);
+ virtual ~QmlVariantAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+ QVariant from() const;
+ void setFrom(const QVariant &);
+
+ QVariant to() const;
+ void setTo(const QVariant &);
+
+ QString easing() const;
+ void setEasing(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *filter();
+ QList<QObject *> *exclude();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(QVariant);
+ void toChanged(QVariant);
+ void easingChanged(const QString &);
+ void propertiesChanged(const QString &);
+};
+QML_DECLARE_TYPE(QmlVariantAnimation)
+
+#endif // QMLANIMATION_H
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h
new file mode 100644
index 0000000..e5a7384
--- /dev/null
+++ b/src/declarative/util/qmlanimation_p.h
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLANIMATION_P_H
+#define QMLANIMATION_P_H
+
+#include <private/qobject_p.h>
+#include <private/qmlnullablevalue_p.h>
+#include <private/qvariantanimation_p.h>
+#include <QtCore/QPauseAnimation>
+#include <QtCore/QVariantAnimation>
+#include <QtCore/QAnimationGroup>
+#include <QtGui/QColor>
+#include <QtDeclarative/qmlanimation.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmltimelinevalueproxy.h>
+
+QT_BEGIN_NAMESPACE
+
+//interface for classes that provide animation actions for QActionAnimation
+class QAbstractAnimationAction
+{
+public:
+ virtual ~QAbstractAnimationAction() {}
+ virtual void doAction() = 0;
+};
+
+//templated animation action
+//allows us to specify an action that calls a function of a class.
+//(so that class doesn't have to inherit QmlAbstractAnimationAction)
+template<class T, void (T::*method)()>
+class QAnimationActionProxy : public QAbstractAnimationAction
+{
+public:
+ QAnimationActionProxy(T *p) : m_p(p) {}
+ virtual void doAction() { (m_p->*method)(); }
+
+private:
+ T *m_p;
+};
+
+//performs an action of type QAbstractAnimationAction
+class QActionAnimation : public QAbstractAnimation
+{
+public:
+ QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {}
+ QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0)
+ : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped) {}
+ virtual int duration() const { return 0; }
+ void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ animAction = action;
+ policy = p;
+ }
+protected:
+ virtual void updateCurrentTime(int) {}
+
+ virtual void updateState(State /*oldState*/, State newState)
+ {
+ if (newState == Running) {
+ if (animAction)
+ animAction->doAction();
+ } else if (newState == Stopped && policy == DeleteWhenStopped) {
+ delete animAction;
+ animAction = 0;
+ }
+ }
+
+private:
+ QAbstractAnimationAction *animAction;
+ DeletionPolicy policy;
+};
+
+//animates QmlTimeLineValue (assumes start and end values will be reals or compatible)
+class QmlTimeLineValueAnimator : public QVariantAnimation
+{
+public:
+ QmlTimeLineValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {}
+ void setAnimValue(QmlTimeLineValue *value, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ animValue = value;
+ policy = p;
+ }
+ void setFromSourcedValue(bool *value)
+ {
+ fromSourced = value;
+ }
+protected:
+ virtual void updateCurrentValue(const QVariant &value)
+ {
+ if (animValue)
+ animValue->setValue(value.toDouble());
+ }
+ virtual void updateState(State oldState, State newState)
+ {
+ QVariantAnimation::updateState(oldState, newState);
+ if (newState == Running) {
+ //check for new from every loop
+ if (fromSourced)
+ *fromSourced = false;
+ } else if (newState == Stopped && policy == DeleteWhenStopped) {
+ delete animValue;
+ animValue = 0;
+ }
+ }
+
+private:
+ QmlTimeLineValue *animValue;
+ bool *fromSourced;
+ DeletionPolicy policy;
+};
+
+//an animation that just gives a tick
+template<class T, void (T::*method)(int)>
+class QTickAnimationProxy : public QAbstractAnimation
+{
+public:
+ QTickAnimationProxy(T *p, QObject *parent = 0) : QAbstractAnimation(parent), m_p(p) {}
+ virtual int duration() const { return -1; }
+protected:
+ virtual void updateCurrentTime(int msec) { (m_p->*method)(msec); }
+
+private:
+ T *m_p;
+};
+
+class QmlAbstractAnimationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlAbstractAnimation)
+public:
+ QmlAbstractAnimationPrivate()
+ : running(false), finishPlaying(false), repeat(false),
+ connectedTimeLine(false), componentComplete(true), startOnCompletion(false),
+ target(0), group(0) {}
+
+ bool running;
+ bool finishPlaying;
+ bool repeat;
+ bool connectedTimeLine;
+
+ bool componentComplete;
+ bool startOnCompletion;
+
+ void commence();
+
+ QmlNullableValue<QmlMetaProperty> userProperty;
+ QObject *target;
+ QString propertyName;
+
+ QmlMetaProperty property;
+ QmlAnimationGroup *group;
+};
+
+class QmlPauseAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPauseAnimation)
+public:
+ QmlPauseAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), pa(0) {}
+
+ void init();
+
+ QPauseAnimation *pa;
+};
+
+class QmlColorAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlColorAnimation)
+public:
+ QmlColorAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), fromSourced(false), fromIsDefined(false), toIsDefined(false),
+ ca(0), value(this, &QmlColorAnimationPrivate::valueChanged)
+ {
+ if (!colorInterpolator)
+ colorInterpolator = QVariantAnimationPrivate::getInterpolator(QVariant::Color);
+ }
+
+ void init();
+
+ QString easing;
+
+ QColor fromValue;
+ QColor toValue;
+
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ bool fromSourced;
+ bool fromIsDefined;
+ bool toIsDefined;
+
+ QmlTimeLineValueAnimator *ca;
+ virtual void valueChanged(qreal);
+
+ QmlTimeLineValueProxy<QmlColorAnimationPrivate> value;
+
+ static QVariantAnimation::Interpolator colorInterpolator;
+};
+
+class QmlRunScriptActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlRunScriptAction)
+public:
+ QmlRunScriptActionPrivate()
+ : QmlAbstractAnimationPrivate(), proxy(this), rsa(0) {}
+
+ void init();
+
+ QString script;
+ QString file;
+
+ void execute();
+
+ QAnimationActionProxy<QmlRunScriptActionPrivate,
+ &QmlRunScriptActionPrivate::execute> proxy;
+ QActionAnimation *rsa;
+};
+
+class QmlSetPropertyActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSetPropertyAction)
+public:
+ QmlSetPropertyActionPrivate()
+ : QmlAbstractAnimationPrivate(), proxy(this), spa(0) {}
+
+ void init();
+
+ QString properties;
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ QmlNullableValue<QVariant> value;
+
+ void doAction();
+
+ QAnimationActionProxy<QmlSetPropertyActionPrivate,
+ &QmlSetPropertyActionPrivate::doAction> proxy;
+ QActionAnimation *spa;
+};
+
+class QmlParentChangeActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlParentChangeAction)
+public:
+ QmlParentChangeActionPrivate()
+ : QmlAbstractAnimationPrivate() {}
+
+ void init();
+
+ void doAction();
+ QActionAnimation *cpa;
+};
+
+class QmlNumericAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlNumericAnimation)
+public:
+ QmlNumericAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), fromSourced(false), na(0), value(this, &QmlNumericAnimationPrivate::valueChanged) {}
+
+ void init();
+
+ QmlNullableValue<qreal> from;
+ QmlNullableValue<qreal> to;
+
+ QString easing;
+
+ QString properties;
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ bool fromSourced;
+ qreal fromValue;
+ QmlTimeLineValueAnimator *na;
+ virtual void valueChanged(qreal);
+
+ QmlTimeLineValueProxy<QmlNumericAnimationPrivate> value;
+};
+
+class QmlAnimationGroupPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlAnimationGroup)
+public:
+ QmlAnimationGroupPrivate()
+ : QmlAbstractAnimationPrivate(), animations(this), ag(0) {}
+
+ struct AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ AnimationList(QmlAnimationGroupPrivate *p)
+ : anim(p) {}
+ virtual void append(QmlAbstractAnimation *a) {
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ a->setGroup(anim->q_func());
+ }
+ virtual void clear()
+ {
+ for (int i = 0; i < count(); ++i)
+ at(i)->setGroup(0);
+ QmlConcreteList<QmlAbstractAnimation *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ at(i)->setGroup(0);
+ QmlConcreteList<QmlAbstractAnimation *>::removeAt(i);
+ }
+ virtual void insert(int i, QmlAbstractAnimation *a)
+ {
+ QmlConcreteList<QmlAbstractAnimation *>::insert(i, a);
+ a->setGroup(anim->q_func());
+ }
+
+ QmlAnimationGroupPrivate *anim;
+ };
+
+ AnimationList animations;
+ QAnimationGroup *ag;
+};
+
+class QmlVariantAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlVariantAnimation)
+public:
+ QmlVariantAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), fromSourced(false), fromIsDefined(false), toIsDefined(false),
+ va(0), value(this, &QmlVariantAnimationPrivate::valueChanged) {}
+
+ void init();
+
+ QVariant from;
+ QVariant to;
+
+ QString easing;
+
+ QString properties;
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ bool fromSourced;
+ bool fromIsDefined;
+ bool toIsDefined;
+
+ QmlTimeLineValueAnimator *va;
+ virtual void valueChanged(qreal);
+
+ QmlTimeLineValueProxy<QmlVariantAnimationPrivate> value;
+
+ static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress);
+ static void convertVariant(QVariant &variant, QVariant::Type type);
+};
+
+#endif // QMLANIMATION_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbehaviour.cpp b/src/declarative/util/qmlbehaviour.cpp
new file mode 100644
index 0000000..077f666
--- /dev/null
+++ b/src/declarative/util/qmlbehaviour.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qobject_p.h>
+#include "qmlanimation.h"
+#include "qmltransition.h"
+#include "qmlbehaviour.h"
+#include <QtDeclarative/qmlcontext.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QmlBehaviour,Behaviour)
+
+
+class QmlBehaviourData : public QObject
+{
+Q_OBJECT
+public:
+ QmlBehaviourData(QObject *parent)
+ : QObject(parent) {}
+
+ Q_PROPERTY(QVariant endValue READ endValue NOTIFY valuesChanged);
+ Q_PROPERTY(QVariant startValue READ startValue NOTIFY valuesChanged);
+ QVariant endValue() const { return e; }
+ QVariant startValue() const { return s; }
+
+ QVariant e;
+ QVariant s;
+
+Q_SIGNALS:
+ void valuesChanged();
+
+private:
+ friend class QmlBehaviour;
+};
+
+class QmlBehaviourPrivate : public QObjectPrivate
+{
+public:
+ QmlBehaviourPrivate()
+ : context(0), valueData(0), operations(this) {}
+ QmlMetaProperty property;
+ QVariant currentValue;
+
+ QVariant fromValue;
+ QVariant toValue;
+ QmlContext *context;
+ QmlBehaviourData *valueData;
+ class AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ public:
+ AnimationList(QmlBehaviourPrivate *parent) : _parent(parent) {}
+ virtual void append(QmlAbstractAnimation *a)
+ {
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ _parent->group->addAnimation(a->qtAnimation());
+ }
+ virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //###
+ private:
+ QmlBehaviourPrivate *_parent;
+ };
+ AnimationList operations;
+ QSequentialAnimationGroup *group;
+};
+
+/*!
+ \qmlclass Behaviour QmlBehaviour
+ \brief The Behaviour element allows you to specify a default animation for a property change.
+
+ In example below, the rect will use a bounce easing curve over 200 millisecond for any changes to its y property:
+ \code
+ Rect {
+ width: 20; height: 20
+ color: "#00ff00"
+ y: 200 //initial value
+ y: Behaviour {
+ NumericAnimation {
+ easing: "easeOutBounce(amplitude:100)"
+ duration: 200
+ }
+ }
+ }
+ \endcode
+*/
+
+QmlBehaviour::QmlBehaviour(QObject *parent)
+: QmlPropertyValueSource(*(new QmlBehaviourPrivate), parent)
+{
+ Q_D(QmlBehaviour);
+ d->valueData = new QmlBehaviourData(this);
+ d->group = new QSequentialAnimationGroup(this);
+}
+
+/*!
+ \qmlproperty QVariant Behaviour::fromValue
+ This property holds a selector specifying a starting value for the behaviour
+
+ If you only want the behaviour to apply when the change starts at a
+ specific value you can specify fromValue. This selector is used in conjunction
+ with the toValue selector.
+*/
+
+QVariant QmlBehaviour::fromValue() const
+{
+ Q_D(const QmlBehaviour);
+ return d->fromValue;
+}
+
+void QmlBehaviour::setFromValue(const QVariant &v)
+{
+ Q_D(QmlBehaviour);
+ d->fromValue = v;
+}
+
+/*!
+ \qmlproperty QVariant Behaviour::toValue
+ This property holds a selector specifying a ending value for the behaviour
+
+ If you only want the behaviour to apply when the change ends at a
+ specific value you can specify toValue. This selector is used in conjunction
+ with the fromValue selector.
+*/
+
+QVariant QmlBehaviour::toValue() const
+{
+ Q_D(const QmlBehaviour);
+ return d->toValue;
+}
+
+void QmlBehaviour::setToValue(const QVariant &v)
+{
+ Q_D(QmlBehaviour);
+ d->toValue = v;
+}
+
+QmlList<QmlAbstractAnimation *>* QmlBehaviour::operations()
+{
+ Q_D(QmlBehaviour);
+ return &d->operations;
+}
+
+QmlBehaviour::~QmlBehaviour()
+{
+ //### do we need any other cleanup here?
+}
+
+bool QmlBehaviour::_ignore = false;
+void QmlBehaviour::propertyValueChanged()
+{
+ Q_D(QmlBehaviour);
+ if (_ignore)
+ return;
+
+ QVariant newValue = d->property.read();
+
+ if ((!fromValue().isValid() || fromValue() == d->currentValue) &&
+ (!toValue().isValid() || toValue() == newValue)) {
+
+ //### does this clean up everything needed?
+ d->group->stop();
+
+ d->valueData->e = newValue;
+ d->valueData->s = d->currentValue;
+ emit d->valueData->valuesChanged();
+
+ QmlStateOperation::ActionList actions;
+ Action action;
+ action.property = d->property;
+ action.fromValue = d->currentValue;
+ action.toValue = newValue;
+ actions << action;
+
+ _ignore = true;
+ d->property.write(d->currentValue);
+
+ QList<QmlMetaProperty> after;
+ for (int ii = 0; ii < d->operations.count(); ++ii) {
+ d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward);
+ }
+ d->group->start();
+ if (!after.contains(d->property))
+ d->property.write(newValue);
+ _ignore = false;
+ }
+
+ d->currentValue = newValue;
+}
+
+void QmlBehaviour::setTarget(const QmlMetaProperty &property)
+{
+ Q_D(QmlBehaviour);
+ d->property = property;
+ d->currentValue = property.read();
+ d->property.connectNotifier(this, SLOT(propertyValueChanged()));
+}
+
+void QmlBehaviour::classBegin()
+{
+ Q_D(QmlBehaviour);
+ if (!d->context) {
+ d->context = new QmlContext(qmlContext(this), this);
+ d->context->addDefaultObject(d->valueData);
+ }
+ d->context->activate();
+}
+
+void QmlBehaviour::classComplete()
+{
+ Q_D(QmlBehaviour);
+ d->context->deactivate();
+}
+
+#include "qmlbehaviour.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbehaviour.h b/src/declarative/util/qmlbehaviour.h
new file mode 100644
index 0000000..aef53a3
--- /dev/null
+++ b/src/declarative/util/qmlbehaviour.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBEHAVIOUR_H
+#define QMLBEHAVIOUR_H
+
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlAbstractAnimation;
+class QmlBehaviourPrivate;
+class Q_DECLARATIVE_EXPORT QmlBehaviour : public QmlPropertyValueSource,
+ public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlBehaviour)
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QVariant from READ fromValue WRITE setFromValue)
+ Q_PROPERTY(QVariant to READ toValue WRITE setToValue)
+ Q_CLASSINFO("DefaultProperty", "operations")
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations)
+
+public:
+ QmlBehaviour(QObject *parent=0);
+ ~QmlBehaviour();
+
+ QVariant fromValue() const;
+ void setFromValue(const QVariant &);
+ QVariant toValue() const;
+ void setToValue(const QVariant &);
+ virtual void setTarget(const QmlMetaProperty &);
+
+ QmlList<QmlAbstractAnimation *>* operations();
+
+ static bool _ignore;
+
+protected:
+ virtual void classBegin();
+ virtual void classComplete();
+
+private Q_SLOTS:
+ void propertyValueChanged();
+};
+QML_DECLARE_TYPE(QmlBehaviour)
+
+
+#endif // QMLBEHAVIOUR_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlbind.cpp b/src/declarative/util/qmlbind.cpp
new file mode 100644
index 0000000..b45d07d
--- /dev/null
+++ b/src/declarative/util/qmlbind.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmlbindablevalue.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <private/qobject_p.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <private/qmlnullablevalue_p.h>
+#include "qmlbind.h"
+
+QT_BEGIN_NAMESPACE
+class QmlBindPrivate : public QObjectPrivate
+{
+public:
+ QmlBindPrivate() : when(true), obj(0) {}
+
+ bool when;
+ QObject *obj;
+ QString prop;
+ QmlNullableValue<QVariant> value;
+};
+
+QML_DEFINE_TYPE(QmlBind,Bind)
+/*!
+ \qmlclass Bind QmlBind
+ \brief The Bind element allows arbitrary property bindings to be created.
+
+ Sometimes it is necessary to bind to a property of an object that wasn't
+ directly instantiated by QML - generally a property of a class exported
+ to QML by C++. In these cases, regular property binding doesn't work. Bind
+ allows you to bind any value to any property.
+
+ For example, imagine a C++ application that maps an "app.enteredText"
+ property into QML. You could use Bind to update the enteredText property
+ like this.
+ \code
+ TextEdit { id: myTextField; text: "Please type here..." }
+ Bind { target: app; property: "enteredText"; value: myTextField.text />
+ \endcode
+ Whenever the text in the TextEdit is updated, the C++ property will be
+ updated also.
+
+ If the bind target or bind property is changed, the bound value is
+ immediately pushed onto the new target.
+
+ \sa {qmlforcpp}{Qt Declarative Markup Language For C++ Programmers}
+ */
+/*!
+ \internal
+ \class QmlBind
+ \ingroup group_utility
+ \brief The QmlBind class allows arbitrary property bindings to be created.
+
+ Simple bindings are usually earier to do in-place rather than creating a
+ QmlBind item. For that reason, QmlBind is usually used to transfer property information
+ from Qml to C++.
+
+ \sa cppqml
+ */
+QmlBind::QmlBind(QObject *parent)
+ : QObject(*(new QmlBindPrivate), parent)
+{
+}
+
+QmlBind::~QmlBind()
+{
+}
+
+bool QmlBind::when() const
+{
+ Q_D(const QmlBind);
+ return d->when;
+}
+
+void QmlBind::setWhen(bool v)
+{
+ Q_D(QmlBind);
+ d->when = v;
+ eval();
+}
+
+/*!
+ \qmlproperty Object Bind::target
+
+ The object to be updated.
+ */
+/*!
+ \property QmlBind::target
+ \brief the object to be updated.
+*/
+QObject *QmlBind::object()
+{
+ Q_D(const QmlBind);
+ return d->obj;
+}
+
+void QmlBind::setObject(QObject *obj)
+{
+ Q_D(QmlBind);
+ d->obj = obj;
+ eval();
+}
+
+/*!
+ \qmlproperty string Bind::property
+
+ The property to be updated.
+ */
+/*!
+ \property QmlBind::property
+ \brief the property of the target to be updated.
+*/
+QString QmlBind::property() const
+{
+ Q_D(const QmlBind);
+ return d->prop;
+}
+
+void QmlBind::setProperty(const QString &p)
+{
+ Q_D(QmlBind);
+ d->prop = p;
+ eval();
+}
+
+/*!
+ \qmlproperty any Bind::value
+
+ The value to be set on the target object and property. This can be a
+ constant (which isn't very useful), or a bound expression.
+ */
+/*!
+ \property QmlBind::value
+ \brief the value to bind to.
+*/
+QVariant QmlBind::value() const
+{
+ Q_D(const QmlBind);
+ return d->value.value;
+}
+
+void QmlBind::setValue(const QVariant &v)
+{
+ Q_D(QmlBind);
+ d->value.value = v;
+ d->value.isNull = false;
+ eval();
+}
+
+void QmlBind::eval()
+{
+ Q_D(QmlBind);
+ if (!d->obj || d->value.isNull || !d->when)
+ return;
+
+ QmlMetaProperty prop(d->obj, d->prop);
+ prop.write(d->value.value);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbind.h b/src/declarative/util/qmlbind.h
new file mode 100644
index 0000000..706e202
--- /dev/null
+++ b/src/declarative/util/qmlbind.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBIND_H
+#define QMLBIND_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlBindPrivate;
+class Q_DECLARATIVE_EXPORT QmlBind : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlBind)
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QString property READ property WRITE setProperty)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(bool when READ when WRITE setWhen)
+
+public:
+ QmlBind(QObject *parent=0);
+ ~QmlBind();
+
+ bool when() const;
+ void setWhen(bool);
+
+ QObject *object();
+ void setObject(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+private:
+ void eval();
+};
+QML_DECLARE_TYPE(QmlBind)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp
new file mode 100644
index 0000000..6c7b158
--- /dev/null
+++ b/src/declarative/util/qmlconnection.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlconnection.h"
+#include <QtDeclarative/qmlexpression.h>
+#include "private/qmlboundsignal_p.h"
+#include "private/qobject_p.h"
+#include <QtDeclarative/qmlcontext.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+class QmlConnectionPrivate : public QObjectPrivate
+{
+public:
+ QmlConnectionPrivate() : boundsignal(0), signalSender(0), componentcomplete(false) {}
+
+ QmlBoundSignal *boundsignal;
+ QObject *signalSender;
+ QString script;
+ QString signal;
+ bool componentcomplete;
+};
+
+/*!
+ \qmlclass Connection QmlConnection
+ \brief A Connection object describes generalized connections to signals.
+
+ JavaScript-in-HTML style signal properties do not allow:
+ \list
+ \i connecting to signals with the same name but different parameters
+ \i conformance checking that parameters are correctly named
+ \i multiple connections to the same signal
+ \i connections outside the scope of the signal sender
+ \i signals in classes with coincidentally-named on<Signal> properties
+ \endlist
+
+ When any of these is needed, the Connection object can be used instead.
+ Where a signal could be connected like this:
+
+ \qml
+MouseRegion {
+ onClicked: { foo(x+123,y+456) }
+}
+ \endqml
+
+ An equivalent binding can be made with a Connection object:
+
+ \qml
+MouseRegion {
+ Connection {
+ signal: "clicked(x,y)"
+ script: { foo(x+123,y+456) }
+ }
+}
+ \endqml
+
+ More generally, the Connection object can be a child of some other object than
+ the sender of the signal, and the script is the default attribute:
+
+ \qml
+MouseRegion {
+ id: mr
+}
+...
+Connection {
+ sender: mr
+ signal: "clicked(x,y)"
+ script: { foo(x+123,y+456) }
+}
+ \endqml
+*/
+
+/*!
+ \internal
+ \class QmlConnection
+ \brief The QmlConnection class describes generalized connections to signals.
+
+ QmlSetProperties is a mechanism for connecting a script to be run when
+ some object sends a signal.
+*/
+QmlConnection::QmlConnection(QObject *parent) :
+ QObject(*(new QmlConnectionPrivate), parent)
+{
+}
+
+QmlConnection::~QmlConnection()
+{
+ Q_D(QmlConnection);
+ delete d->boundsignal;
+}
+
+/*!
+ \qmlproperty Object Connection::sender
+ This property holds the object that sends the signal.
+
+ By default, the sender is assumed to be the parent of the Connection.
+*/
+
+/*!
+ \property QmlConnection::sender
+ \brief the object that sends the signal.
+
+ By default, the sender is assumed to be the parent of the Connection.
+
+ Note that the set/get methods are setSignalSender() and signalSender(),
+ due to the pre-existence of QObject::sender().
+*/
+QObject *QmlConnection::signalSender() const
+{
+ Q_D(const QmlConnection);
+ return d->signalSender ? d->signalSender : parent();
+}
+
+void QmlConnection::setSignalSender(QObject *obj)
+{
+ Q_D(QmlConnection);
+ if (d->signalSender == obj)
+ return;
+ disconnectIfValid();
+ d->signalSender = obj;
+ connectIfValid();
+}
+
+void QmlConnection::connectIfValid()
+{
+ Q_D(QmlConnection);
+ if (!d->componentcomplete)
+ return;
+ // boundsignal must not exist
+ if ((d->signalSender || parent()) && !d->signal.isEmpty() && !d->script.isEmpty()) {
+ // create
+ // XXX scope?
+ int sigIdx = -1;
+ int lparen = d->signal.indexOf(QLatin1Char('('));
+ QList<QByteArray> sigparams;
+ if (lparen >= 0 && d->signal.length() > lparen+2) {
+ QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(','));
+ foreach (const QString &s, l) {
+ sigparams.append(s.toLatin1());
+ }
+ }
+ QString signalname = d->signal.left(lparen);
+ QObject *sender = d->signalSender ? d->signalSender : parent();
+ const QMetaObject *mo = sender->metaObject();
+ int methods = mo->methodCount();
+ for (int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QLatin1String(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+ if (methodName == signalname && (lparen<0 || method.parameterNames() == sigparams)) {
+ sigIdx = ii;
+ break;
+ }
+ }
+ if (sigIdx < 0) {
+ qWarning() << "signal" << d->signal << "not found";
+ return;
+ }
+
+ if (sigparams.isEmpty())
+ d->boundsignal = new QmlBoundSignal(qmlContext(this), d->script, sender, sigIdx, this);
+ else
+ d->boundsignal = new QmlBoundSignalProxy(new QmlContext(qmlContext(this),this), d->script, sender, sigIdx, this);
+ }
+}
+
+void QmlConnection::disconnectIfValid()
+{
+ Q_D(QmlConnection);
+ if (!d->componentcomplete)
+ return;
+ if ((d->signalSender || parent()) && !d->signal.isEmpty() && !d->script.isEmpty()) {
+ // boundsignal must exist
+ // destroy
+ delete d->boundsignal;
+ d->boundsignal = 0;
+ }
+}
+
+void QmlConnection::componentComplete()
+{
+ Q_D(QmlConnection);
+ d->componentcomplete=true;
+ connectIfValid();
+}
+
+
+/*!
+ \qmlproperty string Connection::script
+ This property holds the JavaScript executed whenever the signal is sent.
+
+ This is the default attribute of Connection.
+*/
+
+/*!
+ \property QmlConnection::script
+ \brief the JavaScript executed whenever the signal is sent.
+*/
+QString QmlConnection::script() const
+{
+ Q_D(const QmlConnection);
+ return d->script;
+}
+
+void QmlConnection::setScript(const QString& script)
+{
+ Q_D(QmlConnection);
+ if ((d->signalSender || parent()) && !d->signal.isEmpty()) {
+ if (d->script.isEmpty()) {
+ // mustn't exist - create
+ d->script = script;
+ connectIfValid();
+ } else {
+ // must exist - update
+ d->script = script;
+ d->boundsignal->setExpression(script);
+ }
+ } else {
+ d->script = script;
+ }
+}
+
+/*!
+ \qmlproperty string Connection::signal
+ This property holds the signal from the sender to which the script is attached.
+
+ The signal must have its formal parameter names given in parentheses:
+
+ \qml
+Connection {
+ signal: "clicked(x,y)"
+ script: { ... }
+}
+ \endqml
+*/
+
+/*!
+ \property QmlConnection::signal
+ \brief the signal from the sender to which the script is attached.
+*/
+QString QmlConnection::signal() const
+{
+ Q_D(const QmlConnection);
+ return d->signal;
+}
+
+void QmlConnection::setSignal(const QString& sig)
+{
+ Q_D(QmlConnection);
+ if (d->signal == sig)
+ return;
+ disconnectIfValid();
+ d->signal = sig;
+ connectIfValid();
+}
+
+QML_DEFINE_TYPE(QmlConnection,Connection)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlconnection.h b/src/declarative/util/qmlconnection.h
new file mode 100644
index 0000000..57a406b
--- /dev/null
+++ b/src/declarative/util/qmlconnection.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONNECTION_H
+#define QMLCONNECTION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlBoundSignal;
+class QmlContext;
+class QmlConnectionPrivate;
+class Q_DECLARATIVE_EXPORT QmlConnection : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlConnection)
+
+ Q_INTERFACES(QmlParserStatus)
+ Q_CLASSINFO("DefaultProperty", "script")
+ Q_PROPERTY(QObject *sender READ signalSender WRITE setSignalSender)
+ Q_PROPERTY(QString script READ script WRITE setScript)
+ Q_PROPERTY(QString signal READ signal WRITE setSignal)
+
+public:
+ QmlConnection(QObject *parent=0);
+ ~QmlConnection();
+
+ QObject *signalSender() const;
+ void setSignalSender(QObject *);
+ QString script() const;
+ void setScript(const QString&);
+ QString signal() const;
+ void setSignal(const QString&);
+
+private:
+ void disconnectIfValid();
+ void connectIfValid();
+ void componentComplete();
+};
+QML_DECLARE_TYPE(QmlConnection)
+
+#endif
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmldatetimeformatter.cpp b/src/declarative/util/qmldatetimeformatter.cpp
new file mode 100644
index 0000000..ad0e473
--- /dev/null
+++ b/src/declarative/util/qmldatetimeformatter.cpp
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldatetimeformatter.h"
+#include "private/qobject_p.h"
+#include <QtCore/qlocale.h>
+
+QT_BEGIN_NAMESPACE
+//TODO: may need optimisation as the QDateTime member may not be needed?
+// be able to set a locale?
+
+class QmlDateTimeFormatterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDateTimeFormatter)
+public:
+ QmlDateTimeFormatterPrivate() : locale(QLocale::system()), longStyle(false), classComplete(true) {}
+
+ void updateText();
+
+ QDateTime dateTime;
+ QDate date;
+ QTime time;
+ QLocale locale;
+ QString dateTimeText;
+ QString dateText;
+ QString timeText;
+ QString dateTimeFormat; //set for convienience?
+ QString dateFormat;
+ QString timeFormat;
+ bool longStyle;
+ bool classComplete;
+};
+
+/*!
+ \qmlclass DateTimeFormatter QmlDateTimeFormatter
+ \brief The DateTimeFormatter allows you to control the format of a date string.
+
+ \code
+ DateTimeFormatter { id: Formatter; date: System.date }
+ Text { text: Formatter.dateText }
+ \endcode
+
+ By default, the text properties (dateText, timeText, and dateTimeText) will return the
+ date and time using the current system locale's format.
+*/
+
+/*!
+ \internal
+ \class QmlDateTimeFormatter
+ \ingroup group_utility
+ \brief The QmlDateTimeFormatter class allows you to format a date string.
+*/
+
+QmlDateTimeFormatter::QmlDateTimeFormatter(QObject *parent)
+: QObject(*(new QmlDateTimeFormatterPrivate), parent)
+{
+}
+
+QmlDateTimeFormatter::~QmlDateTimeFormatter()
+{
+}
+
+/*!
+ \qmlproperty string DateTimeFormatter::dateText
+ \qmlproperty string DateTimeFormatter::timeText
+ \qmlproperty string DateTimeFormatter::dateTimeText
+
+ Formatted text representations of the \c date, \c time,
+ and \c {date and time}, respectively.
+
+ If there is no explictly specified format the DateTimeFormatter
+ will use the system locale's default 'short' setting.
+
+ \code
+ // specify source date (assuming today is February 19, 2009)
+ DateTimeFormatter { id: formatter; dateTime: Today.date }
+
+ // display the full date and time
+ Text { text: formatter.dateText }
+ \endcode
+
+ Would be equivalent to the following for a US English locale:
+
+ \code
+ // display the date
+ Text { text: "2/19/09" }
+ \endcode
+*/
+QString QmlDateTimeFormatter::dateTimeText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTimeText;
+}
+
+QString QmlDateTimeFormatter::dateText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateText;
+}
+
+QString QmlDateTimeFormatter::timeText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->timeText;
+}
+
+/*!
+ \qmlproperty date DateTimeFormatter::date
+ \qmlproperty time DateTimeFormatter::time
+ \qmlproperty datetime DateTimeFormatter::dateTime
+
+ The source date and time to be used by the formatter.
+
+ \code
+ // setting the date and time
+ DateTimeFormatter { date: System.date; time: System.time }
+ \endcode
+
+ For convienience it is possible to set the datetime property to set both the date and the time.
+ \code
+ // setting the datetime
+ DateTimeFormatter { dateTime: System.dateTime }
+ \endcode
+
+ There can only be one instance of date and time per formatter; if date, time, and dateTime are all
+ set the actual date and time used is not guaranteed.
+
+ \note If no date is set, dateTimeText will be just the date;
+ If no time is set, the dateTimeText will be just the time.
+
+*/
+QDate QmlDateTimeFormatter::date() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->date;
+}
+
+QTime QmlDateTimeFormatter::time() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->time;
+}
+
+QDateTime QmlDateTimeFormatter::dateTime() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTime;
+}
+
+/*!
+ \qmlproperty string DateTimeFormatter::dateFormat
+ \qmlproperty string DateTimeFormatter::timeFormat
+ \qmlproperty string DateTimeFormatter::dateTimeFormat
+
+ Specifies a custom format which the DateTime Formatter can use.
+
+ If there is no explictly specified format the DateTimeFormatter
+ will use the system locale's default 'short' setting.
+
+ The text's format may be modified by setting:
+ \list
+ \i \c dateFormat
+ \i \c timeFormat
+ \i \c dateTimeFormat
+ \endlist
+
+ If only the format for date is defined, the time and dateTime formats will be defined
+ as the system locale default and likewise for the others.
+
+ Syntax for the format is based on the QDateTime::toString() formatting options.
+
+ \code
+ // Format the date such that the dateText is: '1997-12-12'
+ DateTimeFormatter { id: formatter; dateTime: Today.dateTime; formatDate: "yyyy-MM-d" }
+ \endcode
+
+ Assigning an empty string to a particular format will reset it.
+*/
+QString QmlDateTimeFormatter::dateTimeFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTimeFormat;
+}
+
+QString QmlDateTimeFormatter::dateFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateFormat;
+}
+
+QString QmlDateTimeFormatter::timeFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->timeFormat;
+}
+
+/*!
+ \qmlproperty bool DateTimeFormatter::longStyle
+
+ This property causes the formatter to use the system locale's long format rather than short format
+ by default.
+
+ This setting is off by default.
+*/
+bool QmlDateTimeFormatter::longStyle() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->longStyle;
+}
+
+void QmlDateTimeFormatter::setDateTime(const QDateTime &dateTime)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime == dateTime)
+ return;
+ d->dateTime = dateTime;
+ d->date = d->dateTime.date();
+ d->time = d->dateTime.time();
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setTime(const QTime &time)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime.time() == time)
+ return;
+ d->time = time;
+ d->dateTime.setTime(time);
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setDate(const QDate &date)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime.date() == date)
+ return;
+ d->date = date;
+ bool clearTime = d->dateTime.time().isValid() ? false : true; //because setting date generates default time
+ d->dateTime.setDate(date);
+ if (clearTime)
+ d->dateTime.setTime(QTime());
+ d->updateText();
+}
+
+//DateTime formatting may be a combination of date and time?
+void QmlDateTimeFormatter::setDateTimeFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->dateTimeFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setDateFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->dateFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setTimeFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->timeFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setLongStyle(bool longStyle)
+{
+ Q_D(QmlDateTimeFormatter);
+ d->longStyle = longStyle;
+ d->updateText();
+}
+
+void QmlDateTimeFormatterPrivate::updateText()
+{
+ Q_Q(QmlDateTimeFormatter);
+ if (!classComplete)
+ return;
+
+ QString str;
+ QString str1;
+ QString str2;
+
+ Qt::DateFormat defaultFormat = longStyle ? Qt::SystemLocaleLongDate : Qt::SystemLocaleShortDate;
+
+ if (dateFormat.isEmpty())
+ str1 = date.toString(defaultFormat);
+ else
+ str1 = date.toString(dateFormat);
+
+ if (timeFormat.isEmpty())
+ str2 = time.toString(defaultFormat);
+ else
+ str2 = time.toString(timeFormat);
+
+ if (dateTimeFormat.isEmpty())
+ str = dateTime.toString(defaultFormat);
+ //else if (!formatTime.isEmpty() && !formatDate.isEmpty())
+ // str = str1 + QLatin1Char(' ') + str2;
+ else
+ str = dateTime.toString(dateTimeFormat);
+
+ if (dateTimeText == str && dateText == str1 && timeText == str2)
+ return;
+
+ dateTimeText = str;
+ dateText = str1;
+ timeText = str2;
+
+ emit q->textChanged();
+}
+
+void QmlDateTimeFormatter::classBegin()
+{
+ Q_D(QmlDateTimeFormatter);
+ d->classComplete = false;
+}
+
+void QmlDateTimeFormatter::classComplete()
+{
+ Q_D(QmlDateTimeFormatter);
+ d->classComplete = true;
+ d->updateText();
+}
+
+QML_DEFINE_TYPE(QmlDateTimeFormatter, DateTimeFormatter)
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmldatetimeformatter.h b/src/declarative/util/qmldatetimeformatter.h
new file mode 100644
index 0000000..5d11dab
--- /dev/null
+++ b/src/declarative/util/qmldatetimeformatter.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDATETIMEFORMATTER_H
+#define QMLDATETIMEFORMATTER_H
+
+#include <QtCore/qdatetime.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlDateTimeFormatterPrivate;
+class Q_DECLARATIVE_EXPORT QmlDateTimeFormatter : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString dateText READ dateText NOTIFY textChanged)
+ Q_PROPERTY(QString timeText READ timeText NOTIFY textChanged)
+ Q_PROPERTY(QString dateTimeText READ dateTimeText NOTIFY textChanged)
+ Q_PROPERTY(QDate date READ date WRITE setDate)
+ Q_PROPERTY(QTime time READ time WRITE setTime)
+ Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime)
+ Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat)
+ Q_PROPERTY(QString timeFormat READ timeFormat WRITE setTimeFormat)
+ Q_PROPERTY(QString dateTimeFormat READ dateTimeFormat WRITE setDateTimeFormat)
+ Q_PROPERTY(bool longStyle READ longStyle WRITE setLongStyle)
+public:
+ QmlDateTimeFormatter(QObject *parent=0);
+ ~QmlDateTimeFormatter();
+
+ QString dateTimeText() const;
+ QString dateText() const;
+ QString timeText() const;
+
+ QDate date() const;
+ void setDate(const QDate &);
+
+ QTime time() const;
+ void setTime(const QTime &);
+
+ QDateTime dateTime() const;
+ void setDateTime(const QDateTime &);
+
+ QString dateTimeFormat() const;
+ void setDateTimeFormat(const QString &);
+
+ QString dateFormat() const;
+ void setDateFormat(const QString &);
+
+ QString timeFormat() const;
+ void setTimeFormat(const QString &);
+
+ bool longStyle() const;
+ void setLongStyle(bool);
+
+ virtual void classBegin();
+ virtual void classComplete();
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ Q_DISABLE_COPY(QmlDateTimeFormatter)
+ Q_DECLARE_PRIVATE(QmlDateTimeFormatter)
+};
+
+QML_DECLARE_TYPE(QmlDateTimeFormatter)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp
new file mode 100644
index 0000000..d1ecac4
--- /dev/null
+++ b/src/declarative/util/qmlfollow.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <limits.h>
+#include <QtCore/qdebug.h>
+#include "private/qobject_p.h"
+#include "qmlfollow.h"
+#include "private/qmlanimation_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QmlFollow,Follow)
+
+class QmlFollowPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlFollow)
+public:
+ QmlFollowPrivate()
+ : sourceValue(0), maxVelocity(0), lastTime(0)
+ , mass(1.0), spring(0.), damping(0.), velocity(0), epsilon(0.005), enabled(true), mode(Track), clock(this) {}
+
+ QmlMetaProperty property;
+ qreal currentValue;
+ qreal sourceValue;
+ qreal maxVelocity;
+ qreal velocityms;
+ int lastTime;
+ qreal mass;
+ qreal spring;
+ qreal damping;
+ qreal velocity;
+ qreal epsilon;
+ bool enabled;
+
+ enum Mode {
+ Track,
+ Velocity,
+ Spring
+ };
+ Mode mode;
+
+ void tick(int);
+ void updateMode();
+ void start();
+ void stop();
+
+ QTickAnimationProxy<QmlFollowPrivate, &QmlFollowPrivate::tick> clock;
+};
+
+void QmlFollowPrivate::tick(int time)
+{
+ Q_Q(QmlFollow);
+
+ int elapsed = time - lastTime;
+ if (!elapsed)
+ return;
+ if (mode == Spring) {
+ if (elapsed < 10) // capped at 100fps.
+ return;
+ // Real men solve the spring DEs using RK4.
+ // We'll do something much simpler which gives a result that looks fine.
+ int count = (elapsed+5) / 10;
+ for (int i = 0; i < count; ++i) {
+ qreal diff = sourceValue - currentValue;
+ velocity = velocity + spring * diff - damping * velocity;
+ // The following line supports mass. Not sure its worth the extra divisions.
+ // velocity = velocity + spring / mass * diff - damping / mass * velocity;
+ if (maxVelocity > 0.) {
+ // limit velocity
+ if (velocity > maxVelocity)
+ velocity = maxVelocity;
+ else if (velocity < -maxVelocity)
+ velocity = -maxVelocity;
+ }
+ currentValue += velocity * 10.0 / 1000.0;
+ }
+ if (qAbs(velocity) < epsilon && qAbs(sourceValue - currentValue) < epsilon) {
+ velocity = 0.0;
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ lastTime = time - (elapsed - count * 10);
+ } else {
+ qreal moveBy = elapsed * velocityms;
+ qreal diff = sourceValue - currentValue;
+ if (diff > 0) {
+ currentValue += moveBy;
+ if (currentValue > sourceValue) {
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ } else {
+ currentValue -= moveBy;
+ if (currentValue < sourceValue) {
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ }
+ lastTime = time;
+ }
+ emit q->valueChanged(currentValue);
+ property.write(currentValue);
+}
+
+void QmlFollowPrivate::updateMode()
+{
+ if (spring == 0. && maxVelocity == 0.)
+ mode = Track;
+ else if (spring > 0.)
+ mode = Spring;
+ else
+ mode = Velocity;
+}
+
+void QmlFollowPrivate::start()
+{
+ if (!enabled)
+ return;
+
+ if (mode == QmlFollowPrivate::Track) {
+ currentValue = sourceValue;
+ property.write(currentValue);
+ } else if (sourceValue != currentValue && clock.state() != QAbstractAnimation::Running) {
+ lastTime = 0;
+ clock.start(); // infinity??
+ }
+}
+
+void QmlFollowPrivate::stop()
+{
+ clock.stop();
+}
+
+/*!
+ \qmlclass Follow QmlFollow
+ \brief The Follow element allows a property to track a value.
+
+ In example below, Rect2 will follow Rect1 moving with a velocity of up to 200:
+ \code
+ Rect {
+ id: Rect1
+ width: 20; height: 20
+ color: "#00ff00"
+ y: 200 //initial value
+ y: SequentialAnimation {
+ running: true
+ repeat: true
+ NumericAnimation {
+ to: 200
+ easing: "easeOutBounce(amplitude:100)"
+ duration: 2000
+ }
+ PauseAnimation { duration: 1000 }
+ }
+ }
+ Rect {
+ id: Rect2
+ x: Rect1.width
+ width: 20; height: 20
+ color: "#ff0000"
+ y: Follow { source: Rect1.y; velocity: 200 }
+ }
+ \endcode
+*/
+
+QmlFollow::QmlFollow(QObject *parent)
+: QmlPropertyValueSource(*(new QmlFollowPrivate),parent)
+{
+}
+
+QmlFollow::~QmlFollow()
+{
+}
+
+void QmlFollow::setTarget(const QmlMetaProperty &property)
+{
+ Q_D(QmlFollow);
+ d->property = property;
+ d->currentValue = property.read().toDouble();
+}
+
+qreal QmlFollow::sourceValue() const
+{
+ Q_D(const QmlFollow);
+ return d->sourceValue;
+}
+
+/*!
+ \qmlproperty qreal Follow::source
+ This property holds the source value which will be tracked.
+
+ Bind to a property in order to track its changes.
+*/
+
+void QmlFollow::setSourceValue(qreal value)
+{
+ Q_D(QmlFollow);
+ d->sourceValue = value;
+ d->start();
+}
+
+/*!
+ \qmlproperty qreal Follow::velocity
+ This property holds the maximum velocity allowed when tracking the source.
+*/
+
+qreal QmlFollow::velocity() const
+{
+ Q_D(const QmlFollow);
+ return d->maxVelocity;
+}
+
+void QmlFollow::setVelocity(qreal velocity)
+{
+ Q_D(QmlFollow);
+ d->maxVelocity = velocity;
+ d->velocityms = velocity / 1000.0;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty qreal Follow::spring
+ This property holds the spring constant
+
+ The spring constant describes how strongly the target is pulled towards the
+ source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0
+
+ When a spring constant is set and the velocity property is greater than 0,
+ velocity limits the maximum speed.
+*/
+qreal QmlFollow::spring() const
+{
+ Q_D(const QmlFollow);
+ return d->spring;
+}
+
+void QmlFollow::setSpring(qreal spring)
+{
+ Q_D(QmlFollow);
+ d->spring = spring;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty qreal Follow::damping
+ This property holds the spring damping constant
+
+ The damping constant describes how quickly a sprung follower comes to rest.
+ Useful range is 0 - 1.0
+*/
+qreal QmlFollow::damping() const
+{
+ Q_D(const QmlFollow);
+ return d->damping;
+}
+
+void QmlFollow::setDamping(qreal damping)
+{
+ Q_D(QmlFollow);
+ if (damping > 1.)
+ damping = 1.;
+
+ d->damping = damping;
+}
+
+
+/*!
+ \qmlproperty qreal Follow::epsilon
+ This property holds the spring epsilon
+
+ The epsilon is the rate and amount of change in the value which is close enough
+ to 0 to be considered equal to zero. This will depend on the usage of the value.
+ For pixel positions, 0.25 would suffice. For scale, 0.005 will suffice.
+
+ The default is 0.005. Small performance improvements can result in tuning this
+ value.
+*/
+qreal QmlFollow::epsilon() const
+{
+ Q_D(const QmlFollow);
+ return d->epsilon;
+}
+
+void QmlFollow::setEpsilon(qreal epsilon)
+{
+ Q_D(QmlFollow);
+ d->epsilon = epsilon;
+}
+
+/*!
+ \qmlproperty qreal Follow::followValue
+ The current value.
+*/
+
+/*!
+ \qmlproperty bool Follow::enabled
+ This property holds whether the target will track the source.
+*/
+bool QmlFollow::enabled() const
+{
+ Q_D(const QmlFollow);
+ return d->enabled;
+}
+
+void QmlFollow::setEnabled(bool enabled)
+{
+ Q_D(QmlFollow);
+ d->enabled = enabled;
+ if (enabled)
+ d->start();
+ else
+ d->stop();
+}
+
+qreal QmlFollow::value() const
+{
+ Q_D(const QmlFollow);
+ return d->currentValue;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlfollow.h b/src/declarative/util/qmlfollow.h
new file mode 100644
index 0000000..d210592
--- /dev/null
+++ b/src/declarative/util/qmlfollow.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLFOLLOW_H
+#define QMLFOLLOW_H
+
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlFollowPrivate;
+class Q_DECLARATIVE_EXPORT QmlFollow : public QmlPropertyValueSource,
+ public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlFollow)
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue)
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity)
+ Q_PROPERTY(qreal spring READ spring WRITE setSpring)
+ Q_PROPERTY(qreal damping READ damping WRITE setDamping)
+ Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
+ Q_PROPERTY(qreal followValue READ value NOTIFY valueChanged)
+
+public:
+ QmlFollow(QObject *parent=0);
+ ~QmlFollow();
+
+ virtual void setTarget(const QmlMetaProperty &);
+
+ qreal sourceValue() const;
+ void setSourceValue(qreal value);
+ qreal velocity() const;
+ void setVelocity(qreal velocity);
+ qreal spring() const;
+ void setSpring(qreal spring);
+ qreal damping() const;
+ void setDamping(qreal damping);
+ qreal epsilon() const;
+ void setEpsilon(qreal epsilon);
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+ qreal value() const;
+
+Q_SIGNALS:
+ void valueChanged(qreal);
+};
+
+QML_DECLARE_TYPE(QmlFollow)
+
+
+#endif // QFXFOLLOW_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlfont.cpp b/src/declarative/util/qmlfont.cpp
new file mode 100644
index 0000000..c537a83
--- /dev/null
+++ b/src/declarative/util/qmlfont.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qfont.h"
+#include "qmlfont.h"
+
+
+QT_BEGIN_NAMESPACE
+class QmlFontPrivate : public QObjectPrivate
+{
+public:
+ QFont font;
+};
+
+QML_DEFINE_TYPE(QmlFont,Font)
+
+/*!
+ \internal
+ \class QmlFont
+ \ingroup group_utility
+ \brief The QmlFont class provides a font used for drawing text on a QFxView.
+*/
+QmlFont::QmlFont(QObject *parent)
+ : QObject(*(new QmlFontPrivate), parent)
+{
+}
+
+QmlFont::~QmlFont()
+{
+}
+
+/*!
+ \property QmlFont::family
+ \brief the family of the font.
+*/
+QString QmlFont::family() const
+{
+ Q_D(const QmlFont);
+ return d->font.family();
+}
+
+void QmlFont::setFamily(const QString &family)
+{
+ Q_D(QmlFont);
+ d->font.setFamily(family);
+ emit updated();
+}
+
+/*!
+ \property QmlFont::bold
+ \brief whether the font should be bold.
+*/
+bool QmlFont::bold() const
+{
+ Q_D(const QmlFont);
+ return d->font.bold();
+}
+
+void QmlFont::setBold(bool b)
+{
+ Q_D(QmlFont);
+ d->font.setBold(b);
+ emit updated();
+}
+
+/*!
+ \property QmlFont::italic
+ \brief whether the font should be italic.
+*/
+bool QmlFont::italic() const
+{
+ Q_D(const QmlFont);
+ return d->font.italic();
+}
+
+void QmlFont::setItalic(bool b)
+{
+ Q_D(QmlFont);
+ d->font.setItalic(b);
+ emit updated();
+}
+
+/*!
+ \property QmlFont::size
+ \brief the size of the font in points.
+*/
+qreal QmlFont::size() const
+{
+ Q_D(const QmlFont);
+ return d->font.pointSizeF();
+}
+
+void QmlFont::setSize(qreal size)
+{
+ Q_D(QmlFont);
+ d->font.setPointSizeF(size);
+ emit updated();
+}
+
+/*!
+ \brief Returns a QFont representation of the font.
+*/
+QFont QmlFont::font() const
+{
+ Q_D(const QmlFont);
+ return d->font;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlfont.h b/src/declarative/util/qmlfont.h
new file mode 100644
index 0000000..1fee6cb
--- /dev/null
+++ b/src/declarative/util/qmlfont.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLFONT_H
+#define QMLFONT_H
+
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlFontPrivate;
+class Q_DECLARATIVE_EXPORT QmlFont : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlFont)
+
+ Q_PROPERTY(QString family READ family WRITE setFamily)
+ Q_PROPERTY(bool bold READ bold WRITE setBold)
+ Q_PROPERTY(bool italic READ italic WRITE setItalic)
+ Q_PROPERTY(qreal size READ size WRITE setSize)
+
+public:
+ QmlFont(QObject *parent=0);
+ ~QmlFont();
+
+ QString family() const;
+ void setFamily(const QString &);
+
+ bool bold() const;
+ void setBold(bool b);
+
+ bool italic() const;
+ void setItalic(bool b);
+
+ qreal size() const;
+ void setSize(qreal size);
+
+ QFont font() const;
+
+Q_SIGNALS:
+ void updated();
+};
+QML_DECLARE_TYPE(QmlFont)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLFONT_H
diff --git a/src/declarative/util/qmllistaccessor.cpp b/src/declarative/util/qmllistaccessor.cpp
new file mode 100644
index 0000000..da54b6e
--- /dev/null
+++ b/src/declarative/util/qmllistaccessor.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmllistaccessor.h"
+#include <QStringList>
+#include <qmlmetatype.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlListAccessor::QmlListAccessor()
+: type(Invalid)
+{
+}
+
+QmlListAccessor::~QmlListAccessor()
+{
+}
+
+QVariant QmlListAccessor::list() const
+{
+ return d;
+}
+
+void QmlListAccessor::setList(const QVariant &v)
+{
+ d = v;
+
+ if (!d.isValid()) {
+ type = Invalid;
+ } else if (d.type() == QVariant::StringList) {
+ type = StringList;
+ } else if (d.type() != QVariant::UserType) {
+ type = Instance;
+ } else if (QmlMetaType::isObject(d.userType())) {
+ QObject *data = 0;
+ data = *(QObject **)v.constData();
+ d = QVariant::fromValue(data);
+ type = Instance;
+ } else if (QmlMetaType::isQmlList(d.userType())) {
+ type = QmlList;
+ } else if (QmlMetaType::isList(d.userType())) {
+ type = QList;
+ } else {
+ type = Invalid;
+ d = QVariant();
+ }
+}
+
+int QmlListAccessor::count() const
+{
+ switch(type) {
+ case Invalid:
+ return 0;
+ case StringList:
+ return qvariant_cast<QStringList>(d).count();
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ return li->count();
+ }
+ case QList:
+ return QmlMetaType::listCount(d);
+ case Instance:
+ return 1;
+ }
+
+ return 0;
+}
+
+QVariant QmlListAccessor::at(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < count());
+ switch(type) {
+ case Invalid:
+ return QVariant();
+ case StringList:
+ return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx));
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ void *ptr[1];
+ li->at(idx, ptr);
+ return QmlMetaType::fromObject((QObject*)ptr[0], li->type()); //XXX only handles QObject-derived types
+ }
+ case QList:
+ return QmlMetaType::listAt(d, idx);
+ case Instance:
+ return d;
+ }
+
+ return QVariant();
+}
+
+void QmlListAccessor::append(const QVariant &value)
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ {
+ const QString &str = value.toString();
+ qvariant_cast<QStringList>(d).append(str);
+ break;
+ }
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->append(const_cast<void *>(value.constData())); //XXX
+ break;
+ }
+ case QList:
+ QmlMetaType::append(d, value);
+ break;
+ case Instance:
+ //do nothing
+ break;
+ }
+}
+
+void QmlListAccessor::insert(int index, const QVariant &value)
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ {
+ const QString &str = value.toString();
+ qvariant_cast<QStringList>(d).insert(index, str);
+ break;
+ }
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->insert(index, const_cast<void *>(value.constData())); //XXX
+ break;
+ }
+ case QList:
+ //XXX needs implementation
+ qWarning() << "insert function not yet implemented for QLists";
+ break;
+ case Instance:
+ //XXX do nothing?
+ if (index == 0)
+ setList(value);
+ break;
+ }
+}
+
+void QmlListAccessor::removeAt(int index)
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ qvariant_cast<QStringList>(d).removeAt(index);
+ break;
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->removeAt(index);
+ break;
+ }
+ case QList:
+ //XXX needs implementation
+ qWarning() << "removeAt function not yet implemented for QLists";
+ break;
+ case Instance:
+ //XXX do nothing?
+ if (index == 0)
+ setList(QVariant());
+ break;
+ }
+}
+
+void QmlListAccessor::clear()
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ qvariant_cast<QStringList>(d).clear();
+ break;
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->clear();
+ break;
+ }
+ case QList:
+ QmlMetaType::clear(d);
+ break;
+ case Instance:
+ //XXX what should we do here?
+ setList(QVariant());
+ break;
+ }
+}
+
+bool QmlListAccessor::isValid() const
+{
+ return type != Invalid;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmllistaccessor.h b/src/declarative/util/qmllistaccessor.h
new file mode 100644
index 0000000..dd766b2
--- /dev/null
+++ b/src/declarative/util/qmllistaccessor.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLISTACCESSOR_H
+#define QMLLISTACCESSOR_H
+
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlListAccessor
+{
+public:
+ QmlListAccessor();
+ virtual ~QmlListAccessor();
+
+ QVariant list() const;
+ void setList(const QVariant &);
+
+ bool isValid() const;
+
+ int count() const;
+ QVariant at(int) const;
+
+ virtual void append(const QVariant &);
+ virtual void insert(int, const QVariant &);
+ virtual void removeAt(int);
+ virtual void clear();
+
+private:
+ enum Type { Invalid, StringList, QmlList, QList, Instance };
+ Type type;
+ QVariant d;
+};
+
+#endif // QMLLISTACCESSOR_H
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
new file mode 100644
index 0000000..cc85661
--- /dev/null
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -0,0 +1,570 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstack.h>
+#include <QXmlStreamReader>
+#include <private/qmlcustomparser_p.h>
+#include <private/qmlparser_p.h>
+#include "qmlopenmetaobject.h"
+#include <qmlcontext.h>
+#include <qmlbindablevalue.h>
+#include "qmllistmodel.h"
+
+QT_BEGIN_NAMESPACE
+
+#define DATA_ROLE_ID 1
+#define DATA_ROLE_NAME "data"
+
+struct ListInstruction
+{
+ enum { Push, Pop, Value, Set } type;
+ int dataIdx;
+};
+
+struct ListModelData
+{
+ int dataOffset;
+ int instrCount;
+ ListInstruction *instructions() const { return (ListInstruction *)((char *)this + sizeof(ListModelData)); }
+};
+
+Q_DECLARE_METATYPE(QListModelInterface *)
+
+/*!
+ \qmlclass ListModel
+ \brief The ListModel element defines a free-form list data source.
+
+ The ListModel is a simple heirarchy of items containing data roles.
+ For example:
+
+ \code
+ ListModel {
+ id: FruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ }
+ }
+ \endcode
+
+ Item roles (properties) must begin with a lower-case letter. The above example defines a
+ ListModel containing three items, with the roles "name" and "cost".
+
+ The defined model can be used in views such as ListView:
+ \code
+ Component {
+ id: FruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ }
+ }
+
+ ListView {
+ model: FruitModel
+ delegate: FruitDelegate
+ anchors.fill: parent
+ }
+ \endcode
+
+ It is possible for roles to contain list data. In the example below we create a list of fruit attributes:
+
+ \code
+ ListModel {
+ id: FruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ attributes: [
+ ListElement { description: "Core" },
+ ListElement { description: "Deciduous" }
+ ]
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ attributes: [
+ ListElement { description: "Citrus" }
+ ]
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ attributes: [
+ ListElement { description: "Tropical" }
+ ListElement { description: "Seedless" }
+ ]
+ }
+ }
+ \endcode
+
+ The delegate below will list all the fruit attributes:
+ \code
+ Component {
+ id: FruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { id: Name; text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ HorizontalLayout {
+ anchors.top: Name.bottom
+ spacing: 5
+ Text { text: "Attributes:" }
+ Repeater {
+ dataSource: attributes
+ Component { Text { text: description } }
+ }
+ }
+ }
+ }
+ \endcode
+
+*/
+
+struct ModelNode;
+class ListModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ ListModel(QObject *parent=0);
+
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+ Q_PROPERTY(int count READ count)
+ virtual int count() const;
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+
+private:
+ QVariant valueForNode(ModelNode *) const;
+ mutable QStringList roleStrings;
+ friend class ListModelParser;
+ friend struct ModelNode;
+
+ void checkRoles() const;
+ void addRole(const QString &) const;
+ mutable bool _rolesOk;
+ ModelNode *_root;
+};
+
+class ModelObject : public QObject
+{
+ Q_OBJECT
+public:
+ ModelObject(ModelNode *);
+
+ void setValue(const QByteArray &name, const QVariant &val)
+ {
+ _mo->setValue(name, val);
+ }
+
+private:
+ ModelNode *_node;
+ bool _haveProperties;
+ QmlOpenMetaObject *_mo;
+};
+
+struct ModelNode
+{
+ ModelNode();
+ ~ModelNode();
+ QString className;
+
+ QList<QVariant> values;
+ QHash<QString, ModelNode *> properties;
+
+ ListModel *model() {
+ if (!modelCache) {
+ modelCache = new ListModel;
+ modelCache->_root = this;
+ }
+ return modelCache;
+ }
+
+ ModelObject *object() {
+ if (!objectCache) {
+ objectCache = new ModelObject(this);
+ QHash<QString, ModelNode *>::iterator it;
+ for (it = properties.begin(); it != properties.end(); ++it) {
+ if (!(*it)->values.isEmpty())
+ objectCache->setValue(it.key().toLatin1(), (*it)->values.first());
+ }
+ }
+ return objectCache;
+ }
+
+ ListModel *modelCache;
+ ModelObject *objectCache;
+};
+Q_DECLARE_METATYPE(ModelNode *)
+
+ModelObject::ModelObject(ModelNode *node)
+: _node(node), _haveProperties(false), _mo(new QmlOpenMetaObject(this))
+{
+}
+
+ListModel::ListModel(QObject *parent)
+: QListModelInterface(parent), _rolesOk(false), _root(0)
+{
+}
+
+void ListModel::checkRoles() const
+{
+ if (_rolesOk)
+ return;
+
+ for (int ii = 0; ii < _root->values.count(); ++ii) {
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(ii));
+ if (node) {
+ foreach (const QString &role, node->properties.keys())
+ addRole(role);
+ }
+ }
+
+ _rolesOk = true;
+}
+
+void ListModel::addRole(const QString &role) const
+{
+ if (!roleStrings.contains(role))
+ roleStrings << role;
+}
+
+QList<int> ListModel::roles() const
+{
+ checkRoles();
+ QList<int> rv;
+ for (int ii = 0; ii < roleStrings.count(); ++ii)
+ rv << ii;
+ return rv;
+}
+
+QString ListModel::toString(int role) const
+{
+ checkRoles();
+ if (role < roleStrings.count())
+ return roleStrings.at(role);
+ else
+ return QString();
+}
+
+QVariant ListModel::valueForNode(ModelNode *node) const
+{
+ QObject *rv = 0;
+
+ if (!node->properties.isEmpty()) {
+ // Object
+ rv = node->object();
+ } else if (node->values.count() == 0) {
+ // Invalid
+ return QVariant();
+ } else if (node->values.count() == 1) {
+ // Value
+ QVariant &var = node->values[0];
+ ModelNode *valueNode = qvariant_cast<ModelNode *>(var);
+ if (valueNode) {
+ if (!valueNode->properties.isEmpty())
+ rv = valueNode->object();
+ else
+ rv = valueNode->model();
+ } else {
+ return var;
+ }
+ } else if (node->values.count() > 1) {
+ // List
+ rv = node->model();
+ }
+
+ if (rv)
+ return QVariant::fromValue(rv);
+ else
+ return QVariant();
+}
+
+QHash<int,QVariant> ListModel::data(int index, const QList<int> &roles) const
+{
+ checkRoles();
+ QHash<int, QVariant> rv;
+ if (index >= count())
+ return rv;
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return rv;
+
+ for (int ii = 0; ii < roles.count(); ++ii) {
+ const QString &roleString = roleStrings.at(roles.at(ii));
+
+ QHash<QString, ModelNode *>::ConstIterator iter =
+ node->properties.find(roleString);
+ if (iter != node->properties.end()) {
+ ModelNode *row = *iter;
+ rv.insert(roles.at(ii), valueForNode(row));
+ }
+ }
+
+ return rv;
+}
+
+int ListModel::count() const
+{
+ if (!_root) return 0;
+ return _root->values.count();
+}
+
+class ListModelParser : public QmlCustomParser
+{
+public:
+ QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok);
+ bool compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data);
+ void setCustomData(QObject *, const QByteArray &);
+};
+
+bool ListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data)
+{
+ QList<QVariant> values = prop.assignedValues();
+ for(int ii = 0; ii < values.count(); ++ii) {
+ const QVariant &value = values.at(ii);
+
+ if(value.userType() == qMetaTypeId<QmlCustomParserNode>()) {
+ QmlCustomParserNode node =
+ qvariant_cast<QmlCustomParserNode>(value);
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Push;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ QList<QmlCustomParserProperty> props = node.properties();
+ for(int jj = 0; jj < props.count(); ++jj) {
+ const QmlCustomParserProperty &nodeProp = props.at(jj);
+ if(nodeProp.name() == "")
+ return false;
+
+ ListInstruction li;
+ int ref = data.count();
+ data.append(nodeProp.name());
+ data.append('\0');
+ li.type = ListInstruction::Set;
+ li.dataIdx = ref;
+ instr << li;
+
+ if(!compileProperty(nodeProp, instr, data))
+ return false;
+
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ } else {
+
+ QmlParser::Variant variant =
+ qvariant_cast<QmlParser::Variant>(value);
+
+ int ref = data.count();
+ QByteArray d = variant.asScript().toLatin1();
+ d.append('\0');
+ data.append(d);
+
+ ListInstruction li;
+ li.type = ListInstruction::Value;
+ li.dataIdx = ref;
+ instr << li;
+
+ }
+ }
+
+ return true;
+}
+
+QByteArray ListModelParser::compile(const QList<QmlCustomParserProperty> &customProps, bool *ok)
+{
+ *ok = true;
+ QList<ListInstruction> instr;
+ QByteArray data;
+
+ for(int ii = 0; ii < customProps.count(); ++ii) {
+ const QmlCustomParserProperty &prop = customProps.at(ii);
+ if(prop.name() != "") { // isn't default property
+ *ok = false;
+ return QByteArray();
+ }
+
+ if(!compileProperty(prop, instr, data)) {
+ *ok = false;
+ return QByteArray();
+ }
+ }
+
+ int size = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction) +
+ data.count();
+
+ QByteArray rv;
+ rv.resize(size);
+
+ ListModelData *lmd = (ListModelData *)rv.data();
+ lmd->dataOffset = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction);
+ lmd->instrCount = instr.count();
+ for (int ii = 0; ii < instr.count(); ++ii)
+ lmd->instructions()[ii] = instr.at(ii);
+ ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
+
+ return rv;
+}
+
+void ListModelParser::setCustomData(QObject *obj, const QByteArray &d)
+{
+ ListModel *rv = static_cast<ListModel *>(obj);
+
+ ModelNode *root = new ModelNode;
+ rv->_root = root;
+ QStack<ModelNode *> nodes;
+ nodes << root;
+
+ const ListModelData *lmd = (const ListModelData *)d.constData();
+ const char *data = ((const char *)lmd) + lmd->dataOffset;
+
+ for (int ii = 0; ii < lmd->instrCount; ++ii) {
+ const ListInstruction &instr = lmd->instructions()[ii];
+
+ switch(instr.type) {
+ case ListInstruction::Push:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode;
+ n->values << qVariantFromValue(n2);
+ nodes.push(n2);
+ }
+ break;
+
+ case ListInstruction::Pop:
+ nodes.pop();
+ break;
+
+ case ListInstruction::Value:
+ {
+ ModelNode *n = nodes.top();
+ n->values.append(QByteArray(data + instr.dataIdx));
+ }
+ break;
+
+ case ListInstruction::Set:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode;
+ n->properties.insert(QLatin1String(data + instr.dataIdx), n2);
+ nodes.push(n2);
+ }
+ break;
+ }
+ }
+}
+
+QML_DECLARE_TYPE(ListModel)
+QML_DEFINE_CUSTOM_TYPE(ListModel, ListModel, ListModelParser)
+
+// ### FIXME
+class ListElement : public QObject
+{
+Q_OBJECT
+};
+QML_DECLARE_TYPE(ListElement)
+QML_DEFINE_TYPE(ListElement,ListElement)
+
+static void dump(ModelNode *node, int ind)
+{
+ QByteArray indentBa(ind * 4, ' ');
+ const char *indent = indentBa.constData();
+
+ for (int ii = 0; ii < node->values.count(); ++ii) {
+ ModelNode *subNode = qvariant_cast<ModelNode *>(node->values.at(ii));
+ if (subNode) {
+ qWarning().nospace() << indent << "Sub-node " << ii << ": class " << subNode->className;
+ dump(subNode, ind + 1);
+ } else {
+ qWarning().nospace() << indent << "Sub-node " << ii << ": " << node->values.at(ii).toString();
+ }
+ }
+
+ for (QHash<QString, ModelNode *>::ConstIterator iter = node->properties.begin(); iter != node->properties.end(); ++iter) {
+ qWarning().nospace() << indent << "Property " << iter.key() << ":";
+ dump(iter.value(), ind + 1);
+ }
+}
+
+ModelNode::ModelNode()
+: modelCache(0), objectCache(0)
+{
+}
+
+ModelNode::~ModelNode()
+{
+ qDeleteAll(properties);
+ for (int ii = 0; ii < values.count(); ++ii) {
+ ModelNode *node = qvariant_cast<ModelNode *>(values.at(ii));
+ if (node) { delete node; node = 0; }
+ }
+ if (modelCache) { delete modelCache; modelCache = 0; }
+}
+
+QT_END_NAMESPACE
+#include "qmllistmodel.moc"
diff --git a/src/declarative/util/qmllistmodel.h b/src/declarative/util/qmllistmodel.h
new file mode 100644
index 0000000..ddf1e13
--- /dev/null
+++ b/src/declarative/util/qmllistmodel.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLISTMODEL_H
+#define QMLLISTMODEL_H
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qlistmodelinterface.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLISTMODEL_H
diff --git a/src/declarative/util/qmlnullablevalue_p.h b/src/declarative/util/qmlnullablevalue_p.h
new file mode 100644
index 0000000..f16ddd6
--- /dev/null
+++ b/src/declarative/util/qmlnullablevalue_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLNULLABLEVALUE_P_H
+#define QMLNULLABLEVALUE_P_H
+
+template<typename T>
+struct QmlNullableValue
+{
+ QmlNullableValue()
+ : isNull(true), value(T()) {}
+ QmlNullableValue(const QmlNullableValue<T> &o)
+ : isNull(o.isNull), value(o.value) {}
+ QmlNullableValue(const T &t)
+ : isNull(false), value(t) {}
+ QmlNullableValue<T> &operator=(const T &t)
+ { isNull = false; value = t; return *this; }
+ QmlNullableValue<T> &operator=(const QmlNullableValue<T> &o)
+ { isNull = o.isNull; value = o.value; return *this; }
+ operator T() const { return value; }
+
+ void invalidate() { isNull = true; }
+ bool isValid() const { return !isNull; }
+ bool isNull;
+ T value;
+};
+
+#endif // QMLNULLABLEVALUE_P_H
+
diff --git a/src/declarative/util/qmlopenmetaobject.cpp b/src/declarative/util/qmlopenmetaobject.cpp
new file mode 100644
index 0000000..d0dd817
--- /dev/null
+++ b/src/declarative/util/qmlopenmetaobject.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlopenmetaobject.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+
+class QmlOpenMetaObjectPrivate
+{
+public:
+ QmlOpenMetaObjectPrivate() : parent(0), mem(0) {}
+
+ bool autoCreate;
+ QAbstractDynamicMetaObject *parent;
+ int propertyOffset;
+ int signalOffset;
+ QList<QVariant> data;
+ QHash<QByteArray, int> names;
+ QMetaObjectBuilder mob;
+ QMetaObject *mem;
+ QObject *object;
+};
+
+QmlOpenMetaObject::QmlOpenMetaObject(QObject *obj, bool automatic)
+: d(new QmlOpenMetaObjectPrivate)
+{
+ d->autoCreate = automatic;
+ d->object = obj;
+
+ d->mob.setSuperClass(obj->metaObject());
+ d->mob.setClassName(obj->metaObject()->className());
+ d->mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ d->mob.setSuperClass(op->metaObject);
+
+ d->mem = d->mob.toMetaObject();
+ *static_cast<QMetaObject *>(this) = *d->mem;
+ op->metaObject = this;
+ d->propertyOffset = propertyOffset();
+ d->signalOffset = methodOffset();
+}
+
+QmlOpenMetaObject::~QmlOpenMetaObject()
+{
+ if (d->parent)
+ delete d->parent;
+ qFree(d->mem);
+ delete d;
+}
+
+int QmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
+ && id >= d->propertyOffset) {
+ int propId = id - d->propertyOffset;
+ if (c == QMetaObject::ReadProperty) {
+ propertyRead(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = d->data[propId];
+ } else if (c == QMetaObject::WriteProperty) {
+ if (d->data[propId] != *reinterpret_cast<QVariant *>(a[0])) {
+ propertyWrite(propId);
+ d->data[propId] = *reinterpret_cast<QVariant *>(a[0]);
+ activate(d->object, d->signalOffset + propId, 0);
+ }
+ }
+ return -1;
+ } else {
+ if (d->parent)
+ return d->parent->metaCall(c, id, a);
+ else
+ return d->object->qt_metacall(c, id, a);
+ }
+}
+
+QVariant QmlOpenMetaObject::value(int id) const
+{
+ Q_ASSERT(id >= 0 && id < d->data.count());
+ return d->data.at(id);
+}
+
+void QmlOpenMetaObject::setValue(int id, const QVariant &value)
+{
+ Q_ASSERT(id >= 0 && id < d->data.count());
+ d->data[id] = value;
+ activate(d->object, id + d->signalOffset, 0);
+}
+
+QVariant QmlOpenMetaObject::value(const QByteArray &name) const
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->names.find(name);
+ if (iter == d->names.end())
+ return QVariant();
+
+ return d->data.at(*iter);
+}
+
+void QmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->names.find(name);
+
+ int id = -1;
+ if (iter == d->names.end()) {
+ id = doCreateProperty(name.constData()) - d->propertyOffset;
+ } else {
+ id = *iter;
+ }
+
+ if (d->data[id] == val)
+ return;
+
+ d->data[id] = val;
+ activate(d->object, id + d->signalOffset, 0);
+}
+
+int QmlOpenMetaObject::createProperty(const char *name, const char *)
+{
+ if (d->autoCreate)
+ return doCreateProperty(name);
+ else
+ return -1;
+}
+
+int QmlOpenMetaObject::doCreateProperty(const char *name)
+{
+ int id = d->mob.propertyCount();
+ d->mob.addSignal("__" + QByteArray::number(id) + "()");
+ QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
+ build.setDynamic(true);
+ d->data << propertyCreated(id, build);
+ qFree(d->mem);
+ d->mem = d->mob.toMetaObject();
+ *static_cast<QMetaObject *>(this) = *d->mem;
+ d->names.insert(name, id);
+
+ return d->propertyOffset + id;
+}
+
+void QmlOpenMetaObject::propertyRead(int)
+{
+}
+
+void QmlOpenMetaObject::propertyWrite(int)
+{
+}
+
+QVariant QmlOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &)
+{
+ return QVariant();
+}
+
+int QmlOpenMetaObject::count() const
+{
+ return d->data.count();
+}
+
+QByteArray QmlOpenMetaObject::name(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < d->data.count());
+
+ return d->mob.property(idx).name();
+}
+
+QObject *QmlOpenMetaObject::object() const
+{
+ return d->object;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlopenmetaobject.h b/src/declarative/util/qmlopenmetaobject.h
new file mode 100644
index 0000000..239276d
--- /dev/null
+++ b/src/declarative/util/qmlopenmetaobject.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOPENMETAOBJECT_H
+#define QMLOPENMETAOBJECT_H
+
+#include <QtCore/QMetaObject>
+#include <QtCore/private/qobject_p.h>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlOpenMetaObjectPrivate;
+class QMetaPropertyBuilder;
+class Q_DECLARATIVE_EXPORT QmlOpenMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlOpenMetaObject(QObject *, bool = true);
+ ~QmlOpenMetaObject();
+
+ QVariant value(const QByteArray &) const;
+ void setValue(const QByteArray &, const QVariant &);
+ QVariant value(int) const;
+ void setValue(int, const QVariant &);
+
+ int count() const;
+ QByteArray name(int) const;
+
+ QObject *object() const;
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int createProperty(const char *, const char *);
+
+ virtual void propertyRead(int);
+ virtual void propertyWrite(int);
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+
+private:
+ int doCreateProperty(const char *);
+
+ QmlOpenMetaObjectPrivate *d;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLOPENMETAOBJECT_H
diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp
new file mode 100644
index 0000000..e527c1f
--- /dev/null
+++ b/src/declarative/util/qmlpackage.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qmlpackage.h"
+
+
+QT_BEGIN_NAMESPACE
+class QmlPackagePrivate : public QObjectPrivate
+{
+public:
+ QmlPackagePrivate() {}
+
+ QmlConcreteList<QObject *> dataList;
+};
+
+class QmlPackageAttached : public QObject
+{
+Q_OBJECT
+public:
+ QmlPackageAttached(QObject *parent);
+ virtual ~QmlPackageAttached();
+
+ Q_PROPERTY(QString name READ name WRITE setName);
+ QString name() const;
+ void setName(const QString &n);
+
+ static QHash<QObject *, QmlPackageAttached *> attached;
+private:
+ QString _name;
+};
+
+QHash<QObject *, QmlPackageAttached *> QmlPackageAttached::attached;
+
+QmlPackageAttached::QmlPackageAttached(QObject *parent)
+: QObject(parent)
+{
+ attached.insert(parent, this);
+}
+
+QmlPackageAttached::~QmlPackageAttached()
+{
+ attached.remove(parent());
+}
+
+QString QmlPackageAttached::name() const
+{
+ return _name;
+}
+
+void QmlPackageAttached::setName(const QString &n)
+{
+ _name = n;
+}
+
+QmlPackage::QmlPackage(QObject *parent)
+ : QObject(*(new QmlPackagePrivate), parent)
+{
+}
+
+QmlPackage::~QmlPackage()
+{
+ Q_D(QmlPackage);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ delete obj;
+ }
+}
+
+QmlList<QObject *> *QmlPackage::data()
+{
+ Q_D(QmlPackage);
+ return &d->dataList;
+}
+
+bool QmlPackage::hasPart(const QString &name)
+{
+ Q_D(QmlPackage);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QmlPackageAttached *a = QmlPackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return true;
+ }
+ return false;
+}
+
+QObject *QmlPackage::part(const QString &name)
+{
+ Q_D(QmlPackage);
+ if (name.isEmpty() && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QmlPackageAttached *a = QmlPackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return obj;
+ }
+
+ if (name == QLatin1String("default") && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ return 0;
+}
+
+QmlPackageAttached *QmlPackage::qmlAttachedProperties(QObject *o)
+{
+ return new QmlPackageAttached(o);
+}
+
+QML_DEFINE_TYPE(QmlPackage, Package)
+
+QT_END_NAMESPACE
+#include "qmlpackage.moc"
diff --git a/src/declarative/util/qmlpackage.h b/src/declarative/util/qmlpackage.h
new file mode 100644
index 0000000..cc77b6c
--- /dev/null
+++ b/src/declarative/util/qmlpackage.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPACKAGE_H
+#define QMLPACKAGE_H
+
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+/*****************************************************************************
+ *****************************************************************************
+ XXX Experimental
+ *****************************************************************************
+*****************************************************************************/
+
+class QmlPackagePrivate;
+class QmlPackageAttached;
+class QmlPackage : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPackage)
+
+ Q_CLASSINFO("DefaultProperty", "data")
+ Q_PROPERTY(QmlList<QObject *> *data READ data SCRIPTABLE false)
+
+public:
+ QmlPackage(QObject *parent=0);
+ virtual ~QmlPackage();
+
+ QmlList<QObject *> *data();
+
+ QObject *part(const QString & = QString());
+ bool hasPart(const QString &);
+
+ static QmlPackageAttached *qmlAttachedProperties(QObject *);
+};
+QML_DECLARE_TYPE(QmlPackage)
+
+#endif // QMLPACKAGE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp
new file mode 100644
index 0000000..45370e2
--- /dev/null
+++ b/src/declarative/util/qmlscript.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmlbindablevalue.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <private/qobject_p.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <private/qmlnullablevalue_p.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include "qmlscript.h"
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QtDeclarative/qmlinfo.h>
+#include <qfxperf.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlScriptPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlScript);
+
+public:
+ QmlScriptPrivate() : reply(0) {}
+
+ void addScriptToEngine(const QString &, const QString &fileName=QString());
+
+ QString script;
+ QString source;
+ QNetworkReply *reply;
+ QUrl url;
+};
+
+/*!
+ \qmlclass Script QmlScript
+ \brief The Script element adds JavaScript snippets.
+ \ingroup group_utility
+
+ QmlScript is used to add convenient JavaScript "glue" methods to
+ your Qt Declarative application or component. While you can have any JavaScript code
+ within a QmlScript, it is best to limit yourself to defining functions.
+
+ \qml
+ Script {
+ function debugMyComponent() {
+ print(text.text);
+ print(otherinterestingitem.property);
+ }
+ }
+ MouseRegion { onClicked: debugMyComponent() }
+ \endqml
+
+ \note QmlScript executes JavaScript as soon as it is specified.
+ When defining a component, this may be before the execution context is
+ fully specified. As a result some properties or items may not be
+ accessible. By limiting your JavaScript to defining functions that are
+ only executed later once the context is fully defined, this problem is
+ avoided.
+*/
+
+QML_DEFINE_TYPE(QmlScript,Script)
+QmlScript::QmlScript(QObject *parent) : QObject(*(new QmlScriptPrivate), parent)
+{
+}
+
+/*!
+ \qmlproperty string Script::script
+ \default
+ JavaScript code to execute.
+*/
+/*!
+ \property QmlScript::script
+ \brief a script snippet.
+*/
+QString QmlScript::script() const
+{
+ Q_D(const QmlScript);
+ return d->script;
+}
+
+void QmlScript::setScript(const QString &script)
+{
+ Q_D(QmlScript);
+ d->script = script;
+ d->addScriptToEngine(d->script);
+}
+
+/*!
+ \qmlproperty string Script::source
+
+ Setting this property causes the Script element to read JavaScript code from
+ the file specified.
+ */
+/*!
+ \property QmlScript::source
+ \brief the path to a script file.
+*/
+QString QmlScript::source() const
+{
+ Q_D(const QmlScript);
+ return d->source;
+}
+
+void QmlScript::setSource(const QString &source)
+{
+ Q_D(QmlScript);
+ if (d->source == source)
+ return;
+ d->source = source;
+ d->url = qmlContext(this)->resolvedUrl(source);
+
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ if (d->url.scheme() == QLatin1String("file")) {
+ QFile file(d->url.toLocalFile());
+ file.open(QIODevice::ReadOnly);
+ QByteArray ba = file.readAll();
+ d->addScriptToEngine(QString::fromUtf8(ba), d->source);
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->reply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(replyFinished()));
+ }
+}
+
+void QmlScript::replyFinished()
+{
+ Q_D(QmlScript);
+ if (!d->reply->error()) {
+ QByteArray ba = d->reply->readAll();
+ d->addScriptToEngine(QString::fromUtf8(ba), d->source);
+ }
+ d->reply->deleteLater();
+ d->reply = 0;
+}
+
+void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &fileName)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::AddScript> pt;
+#endif
+ Q_Q(QmlScript);
+ QmlEngine *engine = qmlEngine(q);
+ QmlContext *context = qmlContext(q);
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+
+ QScriptContext *currentContext = engine->scriptEngine()->currentContext();
+ QScriptValueList oldScopeChain = currentContext->scopeChain();
+ QScriptValue oldact = currentContext->activationObject();
+
+ for (int i = 0; i < oldScopeChain.size(); ++i) {
+ currentContext->popScope();
+ }
+ for (int i = context->d_func()->scopeChain.size() - 1; i > -1; --i) {
+ currentContext->pushScope(context->d_func()->scopeChain.at(i));
+ }
+
+ currentContext->setActivationObject(context->d_func()->scopeChain.at(0));
+
+ QScriptValue val = scriptEngine->evaluate(script, fileName);
+ if (scriptEngine->hasUncaughtException()) {
+ if (scriptEngine->uncaughtException().isError()){
+ QScriptValue exception = scriptEngine->uncaughtException();
+ if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
+ qWarning() << exception.property(QLatin1String("fileName")).toString()
+ << scriptEngine->uncaughtExceptionLineNumber()
+ << exception.toString();
+
+ } else {
+ qmlInfo(q) << exception.toString();
+ }
+ }
+ }
+
+ currentContext->setActivationObject(oldact);
+
+ for (int i = 0; i < context->d_func()->scopeChain.size(); ++i)
+ currentContext->popScope();
+
+ for (int i = oldScopeChain.size() - 1; i > -1; --i)
+ currentContext->pushScope(oldScopeChain.at(i));
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlscript.h b/src/declarative/util/qmlscript.h
new file mode 100644
index 0000000..dc090bc
--- /dev/null
+++ b/src/declarative/util/qmlscript.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSCRIPT_H
+#define QMLSCRIPT_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlScriptPrivate;
+class Q_DECLARATIVE_EXPORT QmlScript : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlScript)
+
+ Q_PROPERTY(QString script READ script WRITE setScript)
+ Q_PROPERTY(QString source READ source WRITE setSource)
+ Q_CLASSINFO("DefaultProperty", "script")
+
+public:
+ QmlScript(QObject *parent=0);
+
+ QString script() const;
+ void setScript(const QString &);
+
+ QString source() const;
+ void setSource(const QString &);
+
+private Q_SLOTS:
+ void replyFinished();
+};
+QML_DECLARE_TYPE(QmlScript)
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp
new file mode 100644
index 0000000..cb97ed9
--- /dev/null
+++ b/src/declarative/util/qmlsetproperties.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qmlopenmetaobject.h"
+#include "qmlsetproperties.h"
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlinfo.h>
+#include <private/qmlcustomparser_p.h>
+#include <private/qmlparser_p.h>
+#include <QtDeclarative/qmlexpression.h>
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass SetProperties QmlSetProperties
+ \brief The SetProperties element describes new property values for a state.
+
+ SetProperties is a convenience element for changing many properties on a single
+ object. It allows you to specify the property names and values similar to how
+ you normally would specify them for the actual item:
+
+ \code
+ SetProperties {
+ target: myRect
+ x: 52
+ y: 300
+ width: 48
+ }
+ \endcode
+
+ \c target is a property of \c SetProperties, so if the property you want to change
+ is named \e target you will have to use \l SetProperty instead. You should also
+ use \l SetProperty if you want to update the binding for a property,
+ as SetProperties does not support this.
+*/
+
+/*!
+ \internal
+ \class QmlSetProperties
+ \brief The QmlSetProperties class describes new property values for a state.
+
+ \ingroup group_states
+
+ QmlSetProperties is a convenience class for changing many properties on a single
+ object. It allows you to specify the property names and values similar to how
+ you normally would specify them for the actual item:
+
+ \code
+ SetProperties {
+ target: myRect
+ x: 52
+ y: 300
+ width: 48
+ }
+ \endcode
+
+ \c target is a property of \c SetProperties, so if the property you want to change
+ is named \e target you will have to use QmlSetProperty instead. You should also use QmlSetProperty
+ if you want to update the binding for a property, as QmlSetProperties does not support this.
+
+ \sa QmlSetProperty
+*/
+
+/*!
+ \qmlproperty Object SetProperties::target
+ This property holds the object that the properties to change belong to
+*/
+
+/*!
+ \property QmlSetProperties::target
+ \brief the object that the properties to change belong to
+*/
+class QmlSetPropertiesPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSetProperties)
+public:
+ QmlSetPropertiesPrivate() : object(0), decoded(true), restore(true) {}
+
+ QObject *object;
+ QByteArray data;
+ bool decoded;
+ void decode();
+
+ bool restore;
+
+ QList<QPair<QByteArray, QVariant> > properties;
+ QList<QPair<QByteArray, QmlExpression *> > expressions;
+
+ QmlMetaProperty property(const QByteArray &);
+};
+
+class QmlSetPropertiesParser : public QmlCustomParser
+{
+public:
+ void compileList(QList<QPair<QByteArray, QVariant> > &list, const QByteArray &pre, const QmlCustomParserProperty &prop);
+
+ virtual QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+void
+QmlSetPropertiesParser::compileList(QList<QPair<QByteArray, QVariant> > &list,
+ const QByteArray &pre,
+ const QmlCustomParserProperty &prop)
+{
+ QByteArray propName = pre + prop.name();
+
+ QList<QVariant> values = prop.assignedValues();
+ for (int ii = 0; ii < values.count(); ++ii) {
+ const QVariant &value = values.at(ii);
+
+ if (value.userType() == qMetaTypeId<QmlCustomParserNode>()) {
+ continue;
+ } else if(value.userType() == qMetaTypeId<QmlCustomParserProperty>()) {
+
+ QmlCustomParserProperty prop =
+ qvariant_cast<QmlCustomParserProperty>(value);
+ QByteArray pre = propName + ".";
+ compileList(list, pre, prop);
+
+ } else {
+ list << qMakePair(propName, value);
+ }
+ }
+}
+
+QByteArray
+QmlSetPropertiesParser::compile(const QList<QmlCustomParserProperty> &props,
+ bool *ok)
+{
+ *ok = true;
+
+ QList<QPair<QByteArray, QVariant> > data;
+ for(int ii = 0; ii < props.count(); ++ii)
+ compileList(data, QByteArray(), props.at(ii));
+
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ ds << data.count();
+ for(int ii = 0; ii < data.count(); ++ii) {
+ QmlParser::Variant v = qvariant_cast<QmlParser::Variant>(data.at(ii).second);
+ QVariant var;
+ bool isScript = v.isScript();
+ switch(v.type()) {
+ case QmlParser::Variant::Boolean:
+ var = QVariant(v.asBoolean());
+ break;
+ case QmlParser::Variant::Number:
+ var = QVariant(v.asNumber());
+ break;
+ case QmlParser::Variant::String:
+ var = QVariant(v.asString());
+ break;
+ case QmlParser::Variant::Invalid:
+ case QmlParser::Variant::Script:
+ var = QVariant(v.asScript());
+ break;
+ }
+
+ ds << data.at(ii).first << isScript << var;
+ }
+
+ return rv;
+}
+
+void QmlSetPropertiesPrivate::decode()
+{
+ if (decoded)
+ return;
+
+ QDataStream ds(&data, QIODevice::ReadOnly);
+
+ int count;
+ ds >> count;
+ for (int ii = 0; ii < count; ++ii) {
+ QByteArray name;
+ bool isScript;
+ QVariant data;
+ ds >> name;
+ ds >> isScript;
+ ds >> data;
+
+ if (isScript) {
+ QmlExpression *expression = new QmlExpression(qmlContext(object), data.toString(), object);
+ expression->setTrackChange(false);
+ expressions << qMakePair(name, expression);
+ } else {
+ properties << qMakePair(name, data);
+ }
+ }
+
+ decoded = true;
+ data.clear();
+}
+
+void QmlSetPropertiesParser::setCustomData(QObject *object,
+ const QByteArray &data)
+{
+ QmlSetPropertiesPrivate *p =
+ static_cast<QmlSetPropertiesPrivate *>(QObjectPrivate::get(object));
+ p->data = data;
+ p->decoded = false;
+}
+
+QmlSetProperties::QmlSetProperties()
+: QmlStateOperation(*(new QmlSetPropertiesPrivate))
+{
+}
+
+QmlSetProperties::~QmlSetProperties()
+{
+ Q_D(QmlSetProperties);
+ for(int ii = 0; ii < d->expressions.count(); ++ii)
+ delete d->expressions.at(ii).second;
+}
+
+QObject *QmlSetProperties::object() const
+{
+ Q_D(const QmlSetProperties);
+ return d->object;
+}
+
+void QmlSetProperties::setObject(QObject *o)
+{
+ Q_D(QmlSetProperties);
+ d->object = o;
+}
+
+bool QmlSetProperties::restoreEntryValues() const
+{
+ Q_D(const QmlSetProperties);
+ return d->restore;
+}
+
+void QmlSetProperties::setRestoreEntryValues(bool v)
+{
+ Q_D(QmlSetProperties);
+ d->restore = v;
+}
+
+QmlMetaProperty
+QmlSetPropertiesPrivate::property(const QByteArray &property)
+{
+ Q_Q(QmlSetProperties);
+ QList<QByteArray> path = property.split('.');
+
+ QObject *obj = this->object;
+
+ for (int jj = 0; jj < path.count() - 1; ++jj) {
+ const QByteArray &pathName = path.at(jj);
+ QmlMetaProperty prop(obj, QLatin1String(pathName));
+ QObject *objVal = QmlMetaType::toQObject(prop.read());
+ if (!objVal) {
+ qmlInfo(q) << obj->metaObject()->className()
+ << "has no object property named" << pathName;
+ return QmlMetaProperty();
+ }
+ obj = objVal;
+ }
+
+ const QByteArray &name = path.last();
+ QmlMetaProperty prop(obj, QLatin1String(name));
+ if (!prop.isValid()) {
+ qmlInfo(q) << obj->metaObject()->className()
+ << "has no property named" << name;
+ return QmlMetaProperty();
+ } else if (!prop.isWritable()) {
+ qmlInfo(q) << obj->metaObject()->className()
+ << name << "is not writable, and cannot be set.";
+ return QmlMetaProperty();
+ } else {
+ return prop;
+ }
+}
+
+QmlSetProperties::ActionList QmlSetProperties::actions()
+{
+ Q_D(QmlSetProperties);
+
+ d->decode();
+
+ ActionList list;
+
+ for (int ii = 0; ii < d->properties.count(); ++ii) {
+
+ QByteArray property = d->properties.at(ii).first;
+ QmlMetaProperty prop = d->property(property);
+
+ if (prop.isValid()) {
+ Action a;
+ a.restore = restoreEntryValues();
+ a.property = prop;
+ a.fromValue = a.property.read();
+ a.toValue = d->properties.at(ii).second;
+
+ list << a;
+ }
+ }
+
+ for (int ii = 0; ii < d->expressions.count(); ++ii) {
+
+ QByteArray property = d->expressions.at(ii).first;
+ QmlMetaProperty prop = d->property(property);
+
+ if (prop.isValid()) {
+ Action a;
+ a.restore = restoreEntryValues();
+ a.property = prop;
+ a.fromValue = a.property.read();
+ a.toValue = d->expressions.at(ii).second->value();
+
+ list << a;
+ }
+
+ }
+
+ return list;
+}
+
+QML_DEFINE_CUSTOM_TYPE(QmlSetProperties,SetProperties,QmlSetPropertiesParser)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlsetproperties.h b/src/declarative/util/qmlsetproperties.h
new file mode 100644
index 0000000..da5fcf2
--- /dev/null
+++ b/src/declarative/util/qmlsetproperties.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSETPROPERTIES_H
+#define QMLSETPROPERTIES_H
+
+#include <QtDeclarative/qmlstateoperations.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlSetPropertiesPrivate;
+class Q_DECLARATIVE_EXPORT QmlSetProperties : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlSetProperties)
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
+public:
+ QmlSetProperties();
+ ~QmlSetProperties();
+
+ QObject *object() const;
+ void setObject(QObject *);
+
+ bool restoreEntryValues() const;
+ void setRestoreEntryValues(bool);
+
+ virtual ActionList actions();
+};
+QML_DECLARE_TYPE(QmlSetProperties)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSETPROPERTIES_H
diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp
new file mode 100644
index 0000000..abe8301
--- /dev/null
+++ b/src/declarative/util/qmlstate.cpp
@@ -0,0 +1,472 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltransition.h"
+#include "qmlstategroup.h"
+#include "qmlstate_p.h"
+#include "qmlbindablevalue.h"
+#include "qmlstateoperations.h"
+#include "qmlanimation.h"
+#include "qmlanimation_p.h"
+#include "qmlstate.h"
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+Action::Action() : restore(true), bv(0), event(0), actionDone(false)
+{
+}
+
+ActionEvent::~ActionEvent()
+{
+}
+
+QString ActionEvent::name() const
+{
+ return QString();
+}
+
+void ActionEvent::execute()
+{
+}
+
+/*!
+ \internal
+*/
+QmlStateOperation::QmlStateOperation(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ \qmlclass State
+ \brief The State element defines configurations of objects and properties.
+
+ A state is specified as a set of batched changes from the default configuration.
+
+ Note that setting the state of an object from within another state of the same object is
+ inadvisible. Not only would this have the same effect as going directly to the second state
+ it may cause the program to crash.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \internal
+ \class QmlState
+ \brief The QmlState class allows you to define configurations of objects and properties.
+
+ \ingroup group_states
+
+ QmlState allows you to specify a state as a set of batched changes from the default
+ configuration.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+QML_DEFINE_TYPE(QmlState,State)
+QmlState::QmlState(QObject *parent)
+: QObject(*(new QmlStatePrivate), parent)
+{
+}
+
+QmlState::~QmlState()
+{
+}
+
+/*!
+ \qmlproperty string State::name
+ This property holds the name of the state
+
+ Each state should have a unique name.
+*/
+
+/*!
+ \property QmlState::name
+ \brief the name of the state
+
+ Each state should have a unique name.
+*/
+QString QmlState::name() const
+{
+ Q_D(const QmlState);
+ return d->name;
+}
+
+void QmlState::setName(const QString &n)
+{
+ Q_D(QmlState);
+ d->name = n;
+}
+
+bool QmlState::isWhenKnown() const
+{
+ Q_D(const QmlState);
+ return d->when != 0;
+}
+
+/*!
+ \qmlproperty bool State::when
+ This property holds when the state should be applied
+
+ This should be set to an expression that evaluates to true when you want the state to
+ be applied.
+*/
+
+/*!
+ \property QmlState::when
+ \brief when the state should be applied
+
+ This should be set to an expression that evaluates to true when you want the state to
+ be applied.
+*/
+QmlBindableValue *QmlState::when() const
+{
+ Q_D(const QmlState);
+ return d->when;
+}
+
+void QmlState::setWhen(QmlBindableValue *when)
+{
+ Q_D(QmlState);
+ d->when = when;
+ if (d->group)
+ d->group->updateAutoState();
+}
+
+/*!
+ \qmlproperty string State::extends
+ This property holds the state that this state extends
+
+ The state being extended is treated as the base state in regards to
+ the changes specified by the extending state.
+*/
+
+/*!
+ \property QmlState::extends
+ \brief the state that this state extends
+
+ The state being extended is treated as the base state in regards to
+ the changes specified by the extending state.
+
+ \sa operations
+*/
+QString QmlState::extends() const
+{
+ Q_D(const QmlState);
+ return d->extends;
+}
+
+void QmlState::setExtends(const QString &extends)
+{
+ Q_D(QmlState);
+ d->extends = extends;
+}
+
+/*!
+ \qmlproperty list<StateOperation> State::operations
+ This property holds the changes to apply for this state
+ \default
+
+ By default these changes are applied against the default state. If the state
+ extends another state, then the changes are applied against the state being
+ extended.
+*/
+
+/*!
+ \property QmlState::operations
+ \brief the changes to apply for this state
+
+ By default these changes are applied against the default state. If the state
+ extends another state, then the changes are applied against the state being
+ extended.
+*/
+QmlList<QmlStateOperation *> *QmlState::operations()
+{
+ Q_D(QmlState);
+ return &d->operations;
+}
+
+QmlState &QmlState::operator<<(QmlStateOperation *op)
+{
+ Q_D(QmlState);
+ d->operations.append(op);
+ return *this;
+}
+
+#if 0
+static void dump(const QmlStateOperation::ActionList &list)
+{
+ if (!QString(getenv("STATE_DEBUG")).isEmpty())
+ return;
+
+ for (int ii = 0; ii < list.count(); ++ii) {
+ const Action &action = list.at(ii);
+ qWarning() << action.property.object << action.property.name << action.toValue;
+ }
+}
+#endif
+
+void QmlStatePrivate::applyBindings()
+{
+ foreach(const Action &action, bindingsList) {
+ if (action.bv && !action.toBinding.isEmpty()) {
+ action.bv->setExpression(action.toBinding);
+ }
+ }
+}
+
+void QmlStatePrivate::complete()
+{
+ Q_Q(QmlState);
+ //apply bindings (now that all transitions are complete)
+ applyBindings();
+
+ for (int ii = 0; ii < reverting.count(); ++ii) {
+ for (int jj = 0; jj < revertList.count(); ++jj) {
+ if (revertList.at(jj).property == reverting.at(ii)) {
+ revertList.removeAt(jj);
+ break;
+ }
+ }
+ }
+ reverting.clear();
+
+ for (int ii = 0; ii < completeList.count(); ++ii) {
+ const QmlMetaProperty &prop = completeList.at(ii).property;
+ prop.write(completeList.at(ii).value);
+ }
+
+ completeList.clear();
+ transition = 0;
+ emit q->completed();
+}
+
+QmlStateOperation::ActionList QmlStatePrivate::generateActionList(QmlStateGroup *group) const
+{
+ QmlStateOperation::ActionList applyList;
+ if (inState)
+ return applyList;
+
+ inState = true;
+
+ if (!extends.isEmpty()) {
+ QList<QmlState *> states = group->states();
+ for (int ii = 0; ii < states.count(); ++ii)
+ if (states.at(ii)->name() == extends)
+ applyList = static_cast<QmlStatePrivate*>(states.at(ii)->d_ptr)->generateActionList(group);
+ }
+
+ foreach(QmlStateOperation *op, operations)
+ applyList << op->actions();
+
+ inState = false;
+ return applyList;
+}
+
+QmlStateGroup *QmlState::stateGroup() const
+{
+ Q_D(const QmlState);
+ return d->group;
+}
+
+void QmlState::setStateGroup(QmlStateGroup *group)
+{
+ Q_D(QmlState);
+ d->group = group;
+}
+
+void QmlState::cancel()
+{
+ Q_D(QmlState);
+ if (d->transition) {
+ d->transition->stop(); //XXX this could potentially trigger a complete in rare circumstances
+ d->transition = 0;
+ }
+}
+
+void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *revert)
+{
+ Q_D(QmlState);
+
+ cancel();
+ if (revert)
+ revert->cancel();
+ d->revertList.clear();
+ d->reverting.clear();
+ d->bindingsList.clear();
+
+ if (revert)
+ d->revertList = static_cast<QmlStatePrivate*>(revert->d_ptr)->revertList;
+ QmlStateOperation::RevertActionList additionalReverts;
+
+ QmlStateOperation::ActionList applyList = d->generateActionList(group);
+
+ for (int ii = 0; ii < applyList.count(); ++ii) {
+ const Action &action = applyList.at(ii);
+ if (action.event || !action.restore)
+ continue;
+
+ bool found = false;
+ for (int jj = 0; !found && jj < d->revertList.count(); ++jj) {
+ if (d->revertList.at(jj).property == action.property)
+ found = true;
+ }
+ if (!found) {
+ RevertAction r(action);
+ additionalReverts << r;
+ }
+ }
+ for (int ii = 0; ii < d->revertList.count(); ++ii) {
+ bool found = false;
+ for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ const Action &action = applyList.at(jj);
+ if (action.property == d->revertList.at(ii).property)
+ found = true;
+ }
+ if (!found) {
+ QVariant cur = d->revertList.at(ii).property.read();
+ Action a;
+ a.property = d->revertList.at(ii).property;
+ a.fromValue = cur;
+ a.toValue = d->revertList.at(ii).value;
+ a.toBinding = d->revertList.at(ii).binding;
+ if (!a.toBinding.isEmpty()) {
+ a.fromBinding = d->revertList.at(ii).bv->expression();
+ a.bv = d->revertList.at(ii).bv;
+ }
+ applyList << a;
+ d->reverting << d->revertList.at(ii).property;
+ }
+ }
+ d->revertList << additionalReverts;
+
+ //apply all changes, and work out any ending positions for bindings
+ //then rewind all changes and proceed as normal
+ //### 4 foreach loops!
+ ////////////////////////////////////////////////////////////////////
+ foreach(const Action &action, applyList) {
+ if (stateChangeDebug())
+ qWarning() << " Action:" << action.property.object() << action.property.name() << action.toValue;
+
+ if (action.bv && !action.toBinding.isEmpty()) {
+ d->bindingsList << action;
+ action.bv->clearExpression();
+ }
+ }
+
+ if (!d->bindingsList.isEmpty()) {
+ foreach(const Action &action, applyList) {
+ if (action.bv && !action.toBinding.isEmpty()) {
+ action.bv->setExpression(action.toBinding);
+ } else if (!action.event) {
+ action.property.write(action.toValue);
+ }
+ }
+
+ for (int ii = 0; ii < applyList.size(); ++ii) {
+ Action *action = &applyList[ii];
+ if (action->event)
+ continue;
+
+ const QmlMetaProperty &prop = action->property;
+ if (action->bv && !action->toBinding.isEmpty()) {
+ action->toValue = prop.read();
+ }
+ }
+
+ foreach(const Action &action, applyList) {
+ if (action.event)
+ continue;
+
+ if (action.bv && !action.toBinding.isEmpty())
+ action.bv->clearExpression();
+ action.property.write(action.fromValue);
+ }
+ }
+ ////////////////////////////////////////////////////////////////////
+
+ QmlStateOperation::ActionList modList = applyList;
+ QList<QmlMetaProperty> touched;
+ d->completeList.clear();
+ if (trans) {
+ d->transition = trans;
+ trans->prepare(modList, touched, this);
+ for (int ii = 0; ii < modList.count(); ++ii) {
+ const Action &action = modList.at(ii);
+
+ if (action.event) {
+ if (action.actionDone) {
+ modList.removeAt(ii);
+ --ii;
+ }
+ } else {
+ if (action.toValue != action.fromValue) {
+ d->completeList << RevertAction(action, false);
+ }
+
+ if (touched.contains(action.property)) {
+ modList.removeAt(ii);
+ --ii;
+ }
+ }
+ }
+ }
+
+ foreach(const Action &action, modList) {
+ if (action.event)
+ action.event->execute();
+ else
+ action.property.write(action.toValue);
+ }
+ if (!trans)
+ d->applyBindings(); //### merge into above foreach?
+}
+
+QML_DEFINE_TYPE(QmlStateOperation,StateOperation)
+QmlStateOperation::ActionList QmlStateOperation::actions()
+{
+ return ActionList();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h
new file mode 100644
index 0000000..0b8d82a
--- /dev/null
+++ b/src/declarative/util/qmlstate.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATE_H
+#define QMLSTATE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/QSequentialAnimationGroup>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ActionEvent;
+class QmlBindableValue;
+class Action
+{
+public:
+ Action();
+
+ QmlMetaProperty property;
+ bool restore;
+ QVariant fromValue;
+ QVariant toValue;
+ QString fromBinding;
+ QString toBinding;
+ QmlBindableValue *bv;
+ ActionEvent *event;
+ bool actionDone;
+};
+
+class ActionEvent
+{
+public:
+ virtual ~ActionEvent();
+ virtual QString name() const;
+ virtual void execute();
+};
+
+class RevertAction
+{
+public:
+ RevertAction(const Action &a, bool from = true) : bv(0)
+ {
+ property = a.property;
+ if (from) {
+ value = a.fromValue;
+ binding = a.fromBinding;
+ } else {
+ value = a.toValue;
+ binding = a.toBinding;
+ }
+ bv = a.bv;
+ }
+
+ QmlMetaProperty property;
+ QVariant value;
+ QString binding;
+ QmlBindableValue *bv;
+};
+
+class QmlStateGroup;
+class Q_DECLARATIVE_EXPORT QmlStateOperation : public QObject
+{
+ Q_OBJECT
+public:
+ QmlStateOperation(QObject *parent = 0)
+ : QObject(parent) {}
+ typedef QList<Action> ActionList;
+ typedef QList<RevertAction> RevertActionList;
+
+ virtual ActionList actions();
+
+protected:
+ QmlStateOperation(QObjectPrivate &dd, QObject *parent = 0);
+};
+QML_DECLARE_TYPE(QmlStateOperation)
+
+typedef QmlStateOperation::ActionList QmlStateActions;
+
+class QmlTransition;
+class QmlTransitionPrivate;
+class QmlStatePrivate;
+class Q_DECLARATIVE_EXPORT QmlState : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QmlBindableValue *when READ when WRITE setWhen)
+ Q_PROPERTY(QString extends READ extends WRITE setExtends)
+ Q_PROPERTY(QmlList<QmlStateOperation *>* operations READ operations)
+ Q_CLASSINFO("DefaultProperty", "operations")
+
+public:
+ QmlState(QObject *parent=0);
+ virtual ~QmlState();
+
+ QString name() const;
+ void setName(const QString &);
+
+ /*'when' is a QmlBindableValue to limit state changes oscillation
+ due to the unpredictable order of evaluation of bound expressions*/
+ bool isWhenKnown() const;
+ QmlBindableValue *when() const;
+ void setWhen(QmlBindableValue *);
+
+ QString extends() const;
+ void setExtends(const QString &);
+
+ QmlList<QmlStateOperation *> *operations();
+ QmlState &operator<<(QmlStateOperation *);
+
+ void apply(QmlStateGroup *, QmlTransition *, QmlState *revert);
+ void cancel();
+
+ QmlStateGroup *stateGroup() const;
+ void setStateGroup(QmlStateGroup *);
+
+Q_SIGNALS:
+ void completed();
+
+private:
+ Q_DECLARE_PRIVATE(QmlState)
+ Q_DISABLE_COPY(QmlState)
+ friend class QmlTransitionPrivate;
+};
+QML_DECLARE_TYPE(QmlState)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSTATE_H
diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h
new file mode 100644
index 0000000..da8fdcd
--- /dev/null
+++ b/src/declarative/util/qmlstate_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATE_P_H
+#define QMLSTATE_P_H
+
+#include <QtDeclarative/qmlstate.h>
+#include <private/qobject_p.h>
+#include <private/qmlanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlStatePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlState)
+
+public:
+ QmlStatePrivate()
+ : when(0), transition(0), inState(false), group(0) {}
+
+ QString name;
+ QmlBindableValue *when;
+ QmlConcreteList<QmlStateOperation *> operations;
+ QmlTransition *transition;
+ QmlStateOperation::RevertActionList revertList;
+ QList<QmlMetaProperty> reverting;
+ QmlStateOperation::RevertActionList completeList;
+ QmlStateOperation::ActionList bindingsList;
+ QString extends;
+ mutable bool inState;
+ QmlStateGroup *group;
+
+ QmlStateOperation::ActionList generateActionList(QmlStateGroup *) const;
+ void applyBindings();
+ void complete();
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTATE_P_H
diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp
new file mode 100644
index 0000000..57ccd37
--- /dev/null
+++ b/src/declarative/util/qmlstategroup.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qmlbindablevalue.h"
+#include "qmlstategroup.h"
+#include "qmltransition.h"
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+QML_DEFINE_TYPE(QmlStateGroup,StateGroup)
+
+class QmlStateGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlStateGroup)
+public:
+ QmlStateGroupPrivate(QmlStateGroup *p)
+ : nullState(0), states(p), classComplete(true),
+ componentComplete(true), ignoreTrans(false) {}
+
+ QString currentState;
+ QmlState *nullState;
+
+ struct StateList : public QmlConcreteList<QmlState *>
+ {
+ StateList(QmlStateGroup *g)
+ :group(g) {}
+ void append(QmlState *s) {
+ QmlConcreteList<QmlState *>::append(s);
+ if (s) s->setStateGroup(group);
+ }
+ private:
+ QmlStateGroup *group;
+ };
+ StateList states;
+
+ QmlConcreteList<QmlTransition *> transitions;
+ bool classComplete;
+ bool componentComplete;
+ bool ignoreTrans;
+
+ QmlTransition *findTransition(const QString &from, const QString &to);
+ void setCurrentStateInternal(const QString &state, bool = false);
+ void updateAutoState();
+};
+
+QmlStateGroup::QmlStateGroup(QObject *parent)
+ : QObject(*(new QmlStateGroupPrivate(this)), parent)
+{
+}
+
+QmlStateGroup::~QmlStateGroup()
+{
+}
+
+QList<QmlState *> QmlStateGroup::states() const
+{
+ Q_D(const QmlStateGroup);
+ return d->states;
+}
+
+QmlList<QmlState *>* QmlStateGroup::statesProperty()
+{
+ Q_D(QmlStateGroup);
+ return &(d->states);
+}
+
+QmlList<QmlTransition *>* QmlStateGroup::transitionsProperty()
+{
+ Q_D(QmlStateGroup);
+ return &(d->transitions);
+}
+
+QString QmlStateGroup::state() const
+{
+ Q_D(const QmlStateGroup);
+ return d->currentState;
+}
+
+void QmlStateGroup::setState(const QString &state)
+{
+ Q_D(QmlStateGroup);
+ if (d->currentState == state)
+ return;
+
+ d->setCurrentStateInternal(state);
+
+ d->currentState = state;
+ emit stateChanged(d->currentState);
+}
+
+void QmlStateGroup::classBegin()
+{
+ Q_D(QmlStateGroup);
+ d->classComplete = false;
+ d->componentComplete = false;
+}
+
+void QmlStateGroup::classComplete()
+{
+ Q_D(QmlStateGroup);
+ d->classComplete = true;
+}
+
+void QmlStateGroup::updateAutoState()
+{
+ Q_D(QmlStateGroup);
+ d->updateAutoState();
+}
+
+void QmlStateGroupPrivate::updateAutoState()
+{
+ Q_Q(QmlStateGroup);
+ if (!classComplete)
+ return;
+
+ bool revert = false;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ QmlState *state = states.at(ii);
+ if (state->isWhenKnown()) {
+ if (!state->name().isEmpty()) {
+ if (state->when() && state->when()->value().toBool()) {
+ if (stateChangeDebug())
+ qWarning() << "Setting auto state due to:"
+ << state->when()->expression();
+ q->setState(state->name());
+ return;
+ } else if (state->name() == currentState) {
+ revert = true;
+ }
+ }
+ }
+ }
+ if (revert)
+ q->setState(QString());
+}
+
+QmlTransition *QmlStateGroupPrivate::findTransition(const QString &from, const QString &to)
+{
+ QmlTransition *highest = 0;
+ int score = 0;
+ bool reversed = false;
+ bool done = false;
+
+ for (int ii = 0; !done && ii < transitions.count(); ++ii) {
+ QmlTransition *t = transitions.at(ii);
+ for (int ii = 0; ii < 2; ++ii)
+ {
+ if (ii && (!t->reversible() ||
+ (t->fromState() == QLatin1String("*") &&
+ t->toState() == QLatin1String("*"))))
+ break;
+ QStringList fromState;
+ QStringList toState;
+
+ fromState = t->fromState().split(QLatin1Char(','));
+ toState = t->toState().split(QLatin1Char(','));
+ if (ii == 1)
+ qSwap(fromState, toState);
+ int tScore = 0;
+ if (fromState.contains(from))
+ tScore += 2;
+ else if (fromState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (toState.contains(to))
+ tScore += 2;
+ else if (toState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (ii == 1)
+ reversed = true;
+ else
+ reversed = false;
+
+ if (tScore == 4) {
+ highest = t;
+ done = true;
+ break;
+ } else if (tScore > score) {
+ score = tScore;
+ highest = t;
+ }
+ }
+ }
+
+ if (highest)
+ highest->setReversed(reversed);
+
+ return highest;
+}
+
+void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state,
+ bool ignoreTrans)
+{
+ Q_Q(QmlStateGroup);
+ if (!componentComplete)
+ return;
+
+ QmlTransition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state);
+ if (stateChangeDebug()) {
+ qWarning() << this << "Changing state. From" << currentState << ". To" << state;
+ if (transition)
+ qWarning() << " using transition" << transition->fromState()
+ << transition->toState();
+ }
+
+ QmlState *oldState = 0;
+ if (!currentState.isEmpty()) {
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ oldState = states.at(ii);
+ break;
+ }
+ }
+ }
+
+ currentState = state;
+
+ QmlState *newState = 0;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ newState = states.at(ii);
+ break;
+ }
+ }
+
+ if (oldState == 0 || newState == 0) {
+ if (!nullState) { nullState = new QmlState(q); }
+ if (!oldState) oldState = nullState;
+ if (!newState) newState = nullState;
+ }
+
+ newState->apply(q, transition, oldState);
+}
+
+void QmlStateGroup::componentComplete()
+{
+ Q_D(QmlStateGroup);
+ d->updateAutoState();
+ d->componentComplete = true;
+ if (!d->currentState.isEmpty()) {
+ QString cs = d->currentState;
+ d->currentState = QString();
+ d->setCurrentStateInternal(cs, true);
+ }
+}
+
+QmlState *QmlStateGroup::findState(const QString &name) const
+{
+ Q_D(const QmlStateGroup);
+ for (int i = 0; i < d->states.count(); ++i) {
+ QmlState *state = d->states.at(i);
+ if (state->name() == name)
+ return state;
+ }
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstategroup.h b/src/declarative/util/qmlstategroup.h
new file mode 100644
index 0000000..ac1d917
--- /dev/null
+++ b/src/declarative/util/qmlstategroup.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATEGROUP_H
+#define QMLSTATEGROUP_H
+
+#include <QtDeclarative/qmlstate.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlStateGroupPrivate;
+class QmlStateGroup : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+ Q_DECLARE_PRIVATE(QmlStateGroup)
+
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QmlList<QmlState *>* states READ statesProperty DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitionsProperty DESIGNABLE false)
+
+public:
+ QmlStateGroup(QObject * = 0);
+ virtual ~QmlStateGroup();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QmlList<QmlState *>* statesProperty();
+ QList<QmlState *> states() const;
+
+ QmlList<QmlTransition *>* transitionsProperty();
+
+ QmlState *findState(const QString &name) const;
+
+ virtual void classBegin();
+ virtual void classComplete();
+ virtual void componentComplete();
+Q_SIGNALS:
+ void stateChanged(const QString &);
+
+private:
+ friend class QmlState;
+ void updateAutoState();
+};
+QML_DECLARE_TYPE(QmlStateGroup)
+
+#endif // QMLSTATEGROUP_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp
new file mode 100644
index 0000000..02b54f8
--- /dev/null
+++ b/src/declarative/util/qmlstateoperations.cpp
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qobject_p.h>
+#include <qml.h>
+#include <QtDeclarative/qmlcontext.h>
+#include "qmlbindablevalue.h"
+#include "qmlstateoperations.h"
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlParentChangePrivate : public QObjectPrivate
+{
+public:
+ QmlParentChangePrivate() : target(0), parent(0) {}
+
+ QObject *target;
+ QObject *parent;
+};
+
+/*!
+ \preliminary
+ \qmlclass ParentChange
+ \brief The ParentChange element allows you to reparent an object in a state.
+*/
+
+QML_DEFINE_TYPE(QmlParentChange,ParentChange)
+QmlParentChange::QmlParentChange(QObject *parent)
+ : QmlStateOperation(*(new QmlParentChangePrivate), parent)
+{
+}
+
+QmlParentChange::~QmlParentChange()
+{
+}
+
+/*!
+ \qmlproperty Object ParentChange::target
+ This property holds the object to be reparented
+*/
+
+QObject *QmlParentChange::object() const
+{
+ Q_D(const QmlParentChange);
+ return d->target;
+}
+void QmlParentChange::setObject(QObject *target)
+{
+ Q_D(QmlParentChange);
+ d->target = target;
+}
+
+/*!
+ \qmlproperty Object ParentChange::parent
+ This property holds the parent for the object in this state
+*/
+
+QObject *QmlParentChange::parent() const
+{
+ Q_D(const QmlParentChange);
+ return d->parent;
+}
+
+void QmlParentChange::setParent(QObject *parent)
+{
+ Q_D(QmlParentChange);
+ d->parent = parent;
+}
+
+QmlStateOperation::ActionList QmlParentChange::actions()
+{
+ Q_D(QmlParentChange);
+ if (!d->target || !d->parent)
+ return ActionList();
+
+ QString propName(QLatin1String("moveToParent"));
+ QmlMetaProperty prop(d->target, propName);
+ if (!prop.isValid()) {
+ qmlInfo(this) << d->target->metaObject()->className()
+ << "has no property named" << propName;
+ return ActionList();
+ }else if (!prop.isWritable()){
+ qmlInfo(this) << d->target->metaObject()->className() << propName
+ << "is not a writable property and cannot be set.";
+ return ActionList();
+ }
+ QVariant cur = prop.read();
+
+ Action a;
+ a.property = prop;
+ a.fromValue = cur;
+ a.toValue = qVariantFromValue(d->parent);
+
+ return ActionList() << a;
+}
+
+class QmlRunScriptPrivate : public QObjectPrivate
+{
+public:
+ QmlRunScriptPrivate() {}
+
+ QString script;
+ QString name;
+};
+
+/*!
+ \qmlclass RunScript QmlRunScript
+ \brief The RunScript element allows you to run a script in a state.
+*/
+QML_DEFINE_TYPE(QmlRunScript,RunScript)
+QmlRunScript::QmlRunScript(QObject *parent)
+: QmlStateOperation(*(new QmlRunScriptPrivate), parent)
+{
+}
+
+QmlRunScript::~QmlRunScript()
+{
+}
+
+/*!
+ \qmlproperty string RunScript::script
+ This property holds the script to run when the state is current.
+*/
+QString QmlRunScript::script() const
+{
+ Q_D(const QmlRunScript);
+ return d->script;
+}
+
+void QmlRunScript::setScript(const QString &s)
+{
+ Q_D(QmlRunScript);
+ d->script = s;
+}
+
+QString QmlRunScript::name() const
+{
+ Q_D(const QmlRunScript);
+ return d->name;
+}
+
+void QmlRunScript::setName(const QString &n)
+{
+ Q_D(QmlRunScript);
+ d->name = n;
+}
+
+void QmlRunScript::execute()
+{
+ Q_D(QmlRunScript);
+ if (!d->script.isEmpty()) {
+ QmlExpression expr(qmlContext(this), d->script, this);
+ expr.setTrackChange(false);
+ expr.value();
+ }
+}
+
+QmlRunScript::ActionList QmlRunScript::actions()
+{
+ ActionList rv;
+ Action a;
+ a.event = this;
+ rv << a;
+ return rv;
+}
+
+/*!
+ \qmlclass SetProperty QmlSetProperty
+ \brief The SetProperty element describes a new property value or binding for a state.
+
+ The code below changes the position of the Rect depending upon
+ the current state:
+
+ \code
+ Rect {
+ id: myrect
+ width: 50
+ height: 50
+ color: "red"
+ }
+
+ states: [
+ State {
+ name: "Position1"
+ SetProperty {
+ target: myrect
+ property: "x"
+ value: 150
+ }
+ SetProperty {
+ target: myrect
+ property: "y"
+ value: 50
+ }
+ },
+ State {
+ name: "Position2"
+ SetProperty {
+ target: myrect
+ property: "y"
+ value: 200
+ }
+ }
+ ]
+ \endcode
+
+ \sa SetProperties
+*/
+
+/*!
+ \internal
+ \class QmlSetProperty
+ \brief The QmlSetProperty class describes a new property value or binding for a state.
+
+ \ingroup group_states
+
+ \sa QmlSetProperties
+*/
+
+class QmlSetPropertyPrivate : public QObjectPrivate
+{
+public:
+ QmlSetPropertyPrivate() : obj(0) {}
+
+ QObject *obj;
+ QString prop;
+ QVariant value;
+ QString binding;
+};
+
+QML_DEFINE_TYPE(QmlSetProperty,SetProperty)
+
+QmlSetProperty::QmlSetProperty(QObject *parent)
+ : QmlStateOperation(*(new QmlSetPropertyPrivate), parent)
+{
+}
+
+QmlSetProperty::~QmlSetProperty()
+{
+}
+
+/*!
+ \qmlproperty Object SetProperty::target
+ This property holds the object the property to change belongs to
+*/
+
+/*!
+ \property QmlSetProperty::target
+ \brief the object the property to change belongs to
+*/
+QObject *QmlSetProperty::object()
+{
+ Q_D(QmlSetProperty);
+ return d->obj;
+}
+
+void QmlSetProperty::setObject(QObject *o)
+{
+ Q_D(QmlSetProperty);
+ d->obj = o;
+}
+
+/*!
+ \qmlproperty string SetProperty::property
+ This property holds the name of the property to change
+*/
+
+/*!
+ \property QmlSetProperty::property
+ \brief the name of the property to change
+*/
+QString QmlSetProperty::property() const
+{
+ Q_D(const QmlSetProperty);
+ return d->prop;
+}
+
+void QmlSetProperty::setProperty(const QString &p)
+{
+ Q_D(QmlSetProperty);
+ d->prop = p;
+}
+
+/*!
+ \qmlproperty variant SetProperty::value
+ This property holds the value to assign to the property
+
+ You should set either a \c value or a \c binding, but not both.
+*/
+
+/*!
+ \property QmlSetProperty::value
+ \brief the value to assign to the property
+
+ You should set either a value or a binding, not both.
+*/
+QVariant QmlSetProperty::value() const
+{
+ Q_D(const QmlSetProperty);
+ return d->value;
+}
+
+void QmlSetProperty::setValue(const QVariant &v)
+{
+ Q_D(QmlSetProperty);
+ d->value = v;
+}
+
+/*!
+ \qmlproperty string SetProperty::binding
+ This property holds the binding to assign to the property
+
+ You should set either a \c value or a \c binding, but not both.
+*/
+
+/*!
+ \property QmlSetProperty::binding
+ \brief the binding to assign to the property
+
+ You should set either a value or a binding, not both.
+*/
+QString QmlSetProperty::binding() const
+{
+ Q_D(const QmlSetProperty);
+ return d->binding;
+}
+
+void QmlSetProperty::setBinding(const QString &binding)
+{
+ Q_D(QmlSetProperty);
+ d->binding = binding;
+}
+
+QmlSetProperty::ActionList QmlSetProperty::actions()
+{
+ Q_D(QmlSetProperty);
+ if (!d->obj)
+ return ActionList();
+
+ QObject *obj = d->obj;
+ QString propName = d->prop;
+
+ if (d->prop.contains(QLatin1Char('.'))) { //handle dot properties
+ QStringList str = d->prop.split(QLatin1Char('.'));
+ for (int ii = 0; ii < str.count()-1; ++ii) {
+ const QString &s = str.at(ii);
+ QmlMetaProperty prop(obj, s);
+ if (!prop.isValid()) {
+ qmlInfo(this) << obj->metaObject()->className()
+ << "has no property named" << s;
+ return ActionList();
+ }
+ QVariant v = prop.read();
+ obj = QmlMetaType::toQObject(v);
+ if (!obj) {
+ qmlInfo(this) << "Unable to coerce value property"
+ << s << "into a QObject";
+ return ActionList();
+ }
+ }
+ propName = str.last();
+ }
+
+ QmlMetaProperty prop(obj, propName);
+ if (!prop.isValid()) {
+ qmlInfo(this) << obj->metaObject()->className()
+ << "has no property named" << propName;
+ return ActionList();
+ }else if (!prop.isWritable()){
+ qmlInfo(this) << obj->metaObject()->className() << propName
+ << "is not a writable property and cannot be set.";
+ return ActionList();
+ }
+ QVariant cur = prop.read();
+
+ Action a;
+ a.property = prop;
+ a.fromValue = cur;
+ a.toValue = d->value;
+ if (!d->binding.isEmpty()) {
+ QmlBindableValue *bv = prop.binding();
+ if (bv) {
+ a.fromBinding = bv->expression();
+ a.bv = bv;
+ }
+ }
+ a.toBinding = d->binding;
+
+ return ActionList() << a;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstateoperations.h b/src/declarative/util/qmlstateoperations.h
new file mode 100644
index 0000000..c7a6d42
--- /dev/null
+++ b/src/declarative/util/qmlstateoperations.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATEOPERATIONS_H
+#define QMLSTATEOPERATIONS_H
+
+#include <QtDeclarative/qmlstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlParentChangePrivate;
+class Q_DECLARATIVE_EXPORT QmlParentChange : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlParentChange)
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QObject *parent READ parent WRITE setParent)
+public:
+ QmlParentChange(QObject *parent=0);
+ ~QmlParentChange();
+
+ QObject *object() const;
+ void setObject(QObject *);
+
+ QObject *parent() const;
+ void setParent(QObject *);
+
+ virtual ActionList actions();
+};
+QML_DECLARE_TYPE(QmlParentChange)
+
+class QmlRunScriptPrivate;
+class Q_DECLARATIVE_EXPORT QmlRunScript : public QmlStateOperation, public ActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlRunScript)
+
+ Q_PROPERTY(QString script READ script WRITE setScript)
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ QmlRunScript(QObject *parent=0);
+ ~QmlRunScript();
+
+ virtual ActionList actions();
+
+ QString script() const;
+ void setScript(const QString &);
+
+ virtual QString name() const;
+ void setName(const QString &);
+
+ virtual void execute();
+};
+QML_DECLARE_TYPE(QmlRunScript)
+
+class QmlSetPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlSetProperty : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlSetProperty)
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QString property READ property WRITE setProperty)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(QString binding READ binding WRITE setBinding)
+
+public:
+ QmlSetProperty(QObject *parent=0);
+ ~QmlSetProperty();
+
+ QObject *object();
+ void setObject(QObject *);
+ QString property() const;
+ void setProperty(const QString &);
+ QVariant value() const;
+ void setValue(const QVariant &);
+ QString binding() const;
+ void setBinding(const QString&);
+
+ virtual ActionList actions();
+};
+QML_DECLARE_TYPE(QmlSetProperty)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSTATEOPERATIONS_H
diff --git a/src/declarative/util/qmltransition.cpp b/src/declarative/util/qmltransition.cpp
new file mode 100644
index 0000000..5931075
--- /dev/null
+++ b/src/declarative/util/qmltransition.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlstate.h"
+#include "qmlstategroup.h"
+#include "qmlstate_p.h"
+#include "qmlbindablevalue.h"
+#include "qmlstateoperations.h"
+#include "qmlanimation.h"
+#include "qmlanimation_p.h"
+#include <QParallelAnimationGroup>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Transition QmlTransition
+ \brief The Transition element defines animated transitions that occur on state changes.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \internal
+ \class QmlTransition
+ \brief The QmlTransition class allows you to define animated transitions that occur on state changes.
+
+ \ingroup group_states
+*/
+
+//ParallelAnimationWrapperallows us to do a "callback" when the animation finishes, rather than connecting
+//and disconnecting signals and slots frequently
+class ParallelAnimationWrapper : public QParallelAnimationGroup
+{
+ Q_OBJECT
+public:
+ ParallelAnimationWrapper(QObject *parent) : QParallelAnimationGroup(parent) {}
+ QmlTransitionPrivate *trans;
+protected:
+ virtual void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+};
+
+class QmlTransitionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlTransition)
+public:
+ QmlTransitionPrivate() : fromState(QLatin1String("*")), toState(QLatin1String("*"))
+ , reversed(false), reversible(false), group(0), endState(0)
+ {
+ operations.parent = this;
+ }
+
+ QString fromState;
+ QString toState;
+ bool reversed;
+ bool reversible;
+ ParallelAnimationWrapper *group;
+ QmlState *endState;
+
+ void init()
+ {
+ Q_Q(QmlTransition);
+ group = new ParallelAnimationWrapper(q);
+ group->trans = this;
+ }
+
+ void complete()
+ {
+ endState->d_func()->complete();
+ }
+
+ class AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ public:
+ AnimationList() : parent(0) {}
+ virtual void append(QmlAbstractAnimation *a);
+ virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //XXX
+
+ QmlTransitionPrivate *parent;
+ };
+ AnimationList operations;
+};
+
+void QmlTransitionPrivate::AnimationList::append(QmlAbstractAnimation *a)
+{
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ parent->group->addAnimation(a->qtAnimation());
+}
+
+void ParallelAnimationWrapper::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
+{
+ QParallelAnimationGroup::updateState(oldState, newState);
+ //XXX not 100% guaranteed to be at end (if there are many zero duration animations at the end)?
+ if (newState == Stopped && currentTime() == duration())
+ {
+ trans->complete();
+ }
+}
+
+
+QML_DEFINE_TYPE(QmlTransition,Transition)
+QmlTransition::QmlTransition(QObject *parent)
+ : QObject(*(new QmlTransitionPrivate), parent)
+{
+ Q_D(QmlTransition);
+ d->init();
+}
+
+QmlTransition::~QmlTransition()
+{
+}
+
+void QmlTransition::stop()
+{
+ Q_D(QmlTransition);
+ d->group->stop();
+}
+
+void QmlTransition::setReversed(bool r)
+{
+ Q_D(QmlTransition);
+ d->reversed = r;
+}
+
+void QmlTransition::prepare(QmlStateOperation::ActionList &actions,
+ QList<QmlMetaProperty> &after,
+ QmlState *endState)
+{
+ Q_D(QmlTransition);
+
+ if (d->reversed) {
+ for (int ii = d->operations.count() - 1; ii >= 0; --ii) {
+ d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Backward);
+ }
+ } else {
+ for (int ii = 0; ii < d->operations.count(); ++ii) {
+ d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward);
+ }
+ }
+
+ d->endState = endState;
+ d->group->start();
+}
+
+/*!
+ \qmlproperty string Transition::fromState
+ \qmlproperty string Transition::toState
+ These properties are selectors indicating which state changes should trigger the transition.
+
+ fromState is used in conjunction with toState to determine when a transition should
+ be applied. By default fromState and toState are both "*" (any state). In the following example,
+ the transition is applied when changing from state1 to state2.
+ \code
+ Transition {
+ fromState: "state1"
+ toState: "state2"
+ ...
+ }
+ \endcode
+*/
+
+/*!
+ \property QmlTransition::fromState
+ \brief a selector indicating which states, when left, should trigger the transition.
+
+ fromState is used in conjunction with toState to determine when a transition should
+ be applied. The default value is "*" (any state).
+*/
+QString QmlTransition::fromState() const
+{
+ Q_D(const QmlTransition);
+ return d->fromState;
+}
+
+void QmlTransition::setFromState(const QString &f)
+{
+ Q_D(QmlTransition);
+ d->fromState = f;
+}
+
+/*!
+ \qmlproperty bool Transition::reversible
+ This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
+
+ The default value is false.
+*/
+
+
+/*!
+ \property QmlTransition::reversible
+ \brief whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
+
+ The default value is false.
+*/
+bool QmlTransition::reversible() const
+{
+ Q_D(const QmlTransition);
+ return d->reversible;
+}
+
+void QmlTransition::setReversible(bool r)
+{
+ Q_D(QmlTransition);
+ d->reversible = r;
+}
+
+/*!
+ \property QmlTransition::toState
+ \brief a selector indicating which states, when entered, should trigger the transition.
+
+ toState is used in conjunction with fromState to determine when a transition should
+ be applied. The default value is "*" (any state).
+*/
+QString QmlTransition::toState() const
+{
+ Q_D(const QmlTransition);
+ return d->toState;
+}
+
+void QmlTransition::setToState(const QString &t)
+{
+ Q_D(QmlTransition);
+ d->toState = t;
+}
+
+/*!
+ \qmlproperty list<Animation> Transition::operations
+ This property holds a list of the animations to be run for this transition.
+
+ The top-level animations in operations are run in parallel.
+ To run them sequentially, you can create a single SequentialAnimation
+ which contains all the animations, and assign that to operations.
+ \default
+*/
+
+/*!
+ \property QmlTransition::operations
+ \brief a list of the transition animations to be run.
+*/
+QmlList<QmlAbstractAnimation *>* QmlTransition::operations()
+{
+ Q_D(QmlTransition);
+ return &d->operations;
+}
+
+QT_END_NAMESPACE
+
+#include "qmltransition.moc"
diff --git a/src/declarative/util/qmltransition.h b/src/declarative/util/qmltransition.h
new file mode 100644
index 0000000..4462b4c
--- /dev/null
+++ b/src/declarative/util/qmltransition.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTRANSITION_H
+#define QMLTRANSITION_H
+
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlstate.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractAnimation;
+class QmlTransitionPrivate;
+class Q_DECLARATIVE_EXPORT QmlTransition : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlTransition)
+
+ Q_PROPERTY(QString fromState READ fromState WRITE setFromState)
+ Q_PROPERTY(QString toState READ toState WRITE setToState)
+ Q_PROPERTY(bool reversible READ reversible WRITE setReversible)
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations)
+ Q_CLASSINFO("DefaultProperty", "operations")
+
+public:
+ QmlTransition(QObject *parent=0);
+ ~QmlTransition();
+
+ QString fromState() const;
+ void setFromState(const QString &);
+
+ QString toState() const;
+ void setToState(const QString &);
+
+ bool reversible() const;
+ void setReversible(bool);
+
+ QmlList<QmlAbstractAnimation *>* operations();
+
+ void prepare(QmlStateOperation::ActionList &actions,
+ QList<QmlMetaProperty> &after,
+ QmlState *endState);
+
+ void setReversed(bool r);
+ void stop();
+};
+QML_DECLARE_TYPE(QmlTransition)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLTRANSITION_H
diff --git a/src/declarative/util/qperformancelog.cpp b/src/declarative/util/qperformancelog.cpp
new file mode 100644
index 0000000..8065f9d
--- /dev/null
+++ b/src/declarative/util/qperformancelog.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qperformancelog.h"
+#include <QHash>
+#include <QDebug>
+
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+
+struct QPerformanceLogData
+{
+ struct Log
+ {
+ Log()
+ : logDescription(0), maxId(-1) {}
+
+ QHash<int, const char *> descriptions;
+ const char *logDescription;
+ int maxId;
+ };
+
+ typedef QHash<QPerformanceLog::LogData *, Log> Logs;
+ Logs logs;
+};
+Q_GLOBAL_STATIC(QPerformanceLogData, performanceLogData);
+
+QPerformanceLog::LogData::LogData(const char *desc)
+: sumTime(0), data(0)
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ QPerformanceLogData::Log log;
+ log.logDescription = desc;
+ logData->logs.insert(this, log);
+
+ timer.start();
+}
+
+QPerformanceLog::LogMetric::LogMetric(LogData *l, int id, const char *desc)
+{
+ if (id < 0)
+ qFatal("QPerformanceLog: Invalid log id %d ('%s')", id, desc);
+
+ QPerformanceLogData *logData = performanceLogData();
+
+ QPerformanceLogData::Logs::Iterator logIter = logData->logs.find(l);
+ if (logIter == logData->logs.end())
+ qFatal("QPerformanceLog: Unable to locate log for metric '%s'", desc);
+ QPerformanceLogData::Log &log = *logIter;
+ if (log.descriptions.contains(id))
+ qFatal("QPerformanceLog: Duplicate log metric %d ('%s')", id, desc);
+ log.descriptions.insert(id, desc);
+
+ if (log.maxId < id) {
+ log.maxId = id;
+ if (l->data) delete [] l->data;
+ l->data = new unsigned int[2 * (log.maxId + 1)];
+ ::memset(l->data, 0, 2 * (log.maxId + 1) * sizeof(unsigned int));
+ }
+}
+
+static void QPerformanceLog_clear(QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl)
+{
+ ::memset(l->data, 0, 2 * (pl->maxId + 1) * sizeof(unsigned int));
+}
+
+static void QPerformanceLog_displayData(const QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl)
+{
+ qWarning() << pl->logDescription << "performance data";
+ unsigned int total = 0;
+ for (QHash<int, const char *>::ConstIterator iter = pl->descriptions.begin();
+ iter != pl->descriptions.end();
+ ++iter) {
+
+ int id = iter.key();
+ unsigned int ms = l->data[id * 2];
+ total += ms;
+ unsigned int inst = l->data[id * 2 + 1];
+ float pi = float(ms) / float(inst);
+ qWarning().nospace() << " " << *iter << ": " << ms << " ms over "
+ << inst << " instances (" << pi << " ms/instance)";
+ }
+ qWarning().nospace() << " TOTAL: " << total;
+}
+
+void QPerformanceLog::displayData()
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ for (QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin();
+ iter != logData->logs.end();
+ ++iter) {
+ QPerformanceLog_displayData(iter.key(), &(*iter));
+ }
+}
+
+void QPerformanceLog::clear()
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ for (QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin();
+ iter != logData->logs.end();
+ ++iter) {
+ QPerformanceLog_clear(iter.key(), &(*iter));
+ }
+}
+
+void QPerformanceLog::displayData(LogData *l)
+{
+ QPerformanceLogData *logData = performanceLogData();
+ QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l);
+ if (iter == logData->logs.end())
+ qFatal("QPerformanceLog: Internal corruption - unable to locate log");
+
+ QPerformanceLog_displayData(iter.key(), &(*iter));
+}
+
+void QPerformanceLog::clear(LogData *l)
+{
+ QPerformanceLogData *logData = performanceLogData();
+ QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l);
+ if (iter == logData->logs.end())
+ qFatal("QPerformanceLog: Internal corruption - unable to locate log");
+
+ QPerformanceLog_clear(iter.key(), &(*iter));
+}
+
+#else // Q_ENABLE_PERFORMANCE_LOG
+
+void QPerformanceLog::displayData()
+{
+}
+
+void QPerformanceLog::clear()
+{
+}
+
+#endif // Q_ENABLE_PERFORMANCE_LOG
diff --git a/src/declarative/util/qperformancelog.h b/src/declarative/util/qperformancelog.h
new file mode 100644
index 0000000..3203685
--- /dev/null
+++ b/src/declarative/util/qperformancelog.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPERFORMANCELOG_H
+#define QPERFORMANCELOG_H
+
+#include <QtCore/qdatetime.h>
+namespace QPerformanceLog
+{
+ Q_DECLARATIVE_EXPORT void displayData();
+ Q_DECLARATIVE_EXPORT void clear();
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ struct LogData {
+ LogData(const char *);
+ QTime timer;
+ int sumTime;
+ unsigned int *data;
+ };
+
+ struct LogMetric {
+ LogMetric(LogData *, int, const char *);
+ };
+
+ // Internal
+ void displayData(LogData *);
+ void clear(LogData *);
+#endif
+}
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+
+#define Q_DECLARE_PERFORMANCE_METRIC(name) \
+ enum { name = ValueChoice<0, ValueTracker<0, __LINE__>::value, __LINE__>::value }; \
+ template<int L> \
+ struct ValueTracker<name, L> \
+ { \
+ enum { value = name }; \
+ }; \
+ extern QPerformanceLog::LogMetric metric ## name;
+
+#define Q_DECLARE_PERFORMANCE_LOG(name) \
+ namespace name { \
+ extern QPerformanceLog::LogData log; \
+ inline void displayData() { QPerformanceLog::displayData(&log); } \
+ inline void clear() { QPerformanceLog::clear(&log); } \
+ } \
+ template<int N> \
+ class name ## Timer { \
+ public: \
+ name ## Timer() { \
+ lastSum = name::log.sumTime + name::log.timer.restart(); \
+ name::log.sumTime = 0; \
+ } \
+ ~ name ## Timer() { \
+ name::log.data[2 * N] += name::log.sumTime + name::log.timer.restart(); \
+ ++name::log.data[2 * N + 1]; \
+ name::log.sumTime = lastSum; \
+ } \
+ private: \
+ int lastSum; \
+ }; \
+ namespace name { \
+ template<int N, int L> \
+ struct ValueTracker \
+ { \
+ enum { value = -1 }; \
+ }; \
+ template<int DefNextValue, int NextValue, int L> \
+ struct ValueChoice \
+ { \
+ enum { value = ValueChoice<DefNextValue + 1, ValueTracker<DefNextValue + 1, L>::value, L>::value }; \
+ }; \
+ template<int DefNextValue, int L> \
+ struct ValueChoice<DefNextValue, -1, L> \
+ { \
+ enum { value = DefNextValue }; \
+ }; \
+ } \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_LOG(name, desc) \
+ QPerformanceLog::LogData name::log(desc); \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_METRIC(name, desc) \
+ QPerformanceLog::LogMetric metrix ## name(&log, name, desc);
+
+#else // Q_ENABLE_PERFORMANCE_LOG
+
+#define Q_DECLARE_PERFORMANCE_METRIC(name)
+#define Q_DECLARE_PERFORMANCE_LOG(name) namespace name
+#define Q_DEFINE_PERFORMANCE_LOG(name, desc) namespace name
+#define Q_DEFINE_PERFORMANCE_METRIC(name, desc)
+
+#endif // Q_ENABLE_PERFORMANCE_LOG
+
+#endif // QPERFORMANCELOG_H
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
new file mode 100644
index 0000000..030a44e
--- /dev/null
+++ b/src/declarative/util/util.pri
@@ -0,0 +1,49 @@
+SOURCES += \
+ util/qfxview.cpp \
+ util/qfxperf.cpp \
+ util/qperformancelog.cpp \
+ util/qmlconnection.cpp \
+ util/qmlpackage.cpp \
+ util/qmlscript.cpp \
+ util/qmlanimation.cpp \
+ util/qmlbehaviour.cpp \
+ util/qmlfont.cpp \
+ util/qmlfollow.cpp \
+ util/qmlstate.cpp\
+ util/qmlstateoperations.cpp \
+ util/qmlsetproperties.cpp \
+ util/qmlstategroup.cpp \
+ util/qmltransition.cpp \
+ util/qbindablemap.cpp \
+ util/qmldatetimeformatter.cpp \
+ util/qmllistmodel.cpp\
+ util/qmllistaccessor.cpp \
+ util/qmlopenmetaobject.cpp \
+ util/qmlbind.cpp
+
+HEADERS += \
+ util/qfxview.h \
+ util/qfxperf.h \
+ util/qfxglobal.h \
+ util/qperformancelog.h \
+ util/qmlconnection.h \
+ util/qmlpackage.h \
+ util/qmlscript.h \
+ util/qmlanimation.h \
+ util/qmlanimation_p.h \
+ util/qmlbehaviour.h \
+ util/qmlfont.h \
+ util/qmlfollow.h \
+ util/qmlstate.h\
+ util/qmlstateoperations.h \
+ util/qmlsetproperties.h \
+ util/qmlstate_p.h\
+ util/qmlstategroup.h \
+ util/qmltransition.h \
+ util/qbindablemap.h \
+ util/qmldatetimeformatter.h \
+ util/qmllistmodel.h\
+ util/qmllistaccessor.h \
+ util/qmlopenmetaobject.h \
+ util/qmlnullablevalue_p.h \
+ util/qmlbind.h
diff --git a/src/declarative/widgets/graphicslayouts.cpp b/src/declarative/widgets/graphicslayouts.cpp
new file mode 100644
index 0000000..f2d8dbc
--- /dev/null
+++ b/src/declarative/widgets/graphicslayouts.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicslayouts.h"
+#include <QtGui/qgraphicswidget.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_INTERFACE(QGraphicsLayoutItem)
+QML_DEFINE_INTERFACE(QGraphicsLayout)
+
+class LinearLayoutAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int stretchFactor READ stretchFactor WRITE setStretchFactor NOTIFY stretchChanged)
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged)
+public:
+ LinearLayoutAttached(QObject *parent)
+ : QObject(parent), _stretch(1), _alignment(Qt::AlignCenter)
+ {
+ }
+
+ int stretchFactor() const { return _stretch; }
+ void setStretchFactor(int f)
+ {
+ if (_stretch == f)
+ return;
+
+ _stretch = f;
+ emit stretchChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _stretch);
+ }
+
+ Qt::Alignment alignment() const { return _alignment; }
+ void setAlignment(Qt::Alignment a)
+ {
+ if (_alignment == a)
+ return;
+
+ _alignment = a;
+ emit alignmentChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _alignment);
+ }
+
+Q_SIGNALS:
+ void stretchChanged(QGraphicsLayoutItem*,int);
+ void alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ int _stretch;
+ Qt::Alignment _alignment;
+};
+
+QML_DEFINE_TYPE(QGraphicsLinearLayoutStretchItemObject,QGraphicsLinearLayoutStretchItem)
+
+QGraphicsLinearLayoutStretchItemObject::QGraphicsLinearLayoutStretchItemObject(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QSizeF QGraphicsLinearLayoutStretchItemObject::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ return QSizeF();
+}
+
+QML_DEFINE_TYPE(QGraphicsLinearLayoutObject,QGraphicsLinearLayout)
+
+QGraphicsLinearLayoutObject::QGraphicsLinearLayoutObject(QObject *parent)
+: QObject(parent), _children(this)
+{
+}
+
+QGraphicsLinearLayoutObject::~QGraphicsLinearLayoutObject()
+{
+}
+
+void QGraphicsLinearLayoutObject::insertLayoutItem(int index, QGraphicsLayoutItem *item)
+{
+ insertItem(index, item);
+
+ //connect attached properties
+ if (QObject *obj = attachedProperties.value(item)) {
+ setStretchFactor(item, static_cast<LinearLayoutAttached *>(obj)->stretchFactor());
+ setAlignment(item, static_cast<LinearLayoutAttached *>(obj)->alignment());
+ QObject::connect(obj, SIGNAL(stretchChanged(QGraphicsLayoutItem*,int)),
+ this, SLOT(updateStretch(QGraphicsLayoutItem*,int)));
+ QObject::connect(obj, SIGNAL(alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment)),
+ this, SLOT(updateAlignment(QGraphicsLayoutItem*,Qt::Alignment)));
+ //XXX need to disconnect when widget is removed?
+ }
+}
+
+//XXX is there a better way to do this?
+void QGraphicsLinearLayoutObject::clearChildren()
+{
+ for (int i = 0; i < count(); ++i)
+ removeAt(i);
+}
+
+void QGraphicsLinearLayoutObject::updateStretch(QGraphicsLayoutItem *item, int stretch)
+{
+ QGraphicsLinearLayout::setStretchFactor(item, stretch);
+}
+
+void QGraphicsLinearLayoutObject::updateAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment)
+{
+ QGraphicsLinearLayout::setAlignment(item, alignment);
+}
+
+QHash<QGraphicsLayoutItem*, QObject*> QGraphicsLinearLayoutObject::attachedProperties;
+QObject *QGraphicsLinearLayoutObject::qmlAttachedProperties(QObject *obj)
+{
+ // ### This is not allowed - you must attach to any object
+ if (!qobject_cast<QGraphicsLayoutItem*>(obj))
+ return 0;
+ LinearLayoutAttached *rv = new LinearLayoutAttached(obj);
+ /*if (QGraphicsLinearLayoutObject *lo = qobject_cast<QGraphicsLinearLayoutObject*>(obj->parent()))
+ QObject::connect(rv, SIGNAL(stretchChanged(QGraphicsLayoutItem*,int)),
+ lo, SLOT(updateStretch(QGraphicsLayoutItem*,int)));
+ QObject::connect(rv, SIGNAL(alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment)),
+ lo, SLOT(updateAlignment(QGraphicsLayoutItem*,Qt::Alignment)));*/
+ attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv);
+ return rv;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// QGraphicsGridLayout-related classes
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+class GridLayoutAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int row READ row WRITE setRow)
+ Q_PROPERTY(int column READ column WRITE setColumn)
+ Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan)
+ Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan)
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment)
+public:
+ GridLayoutAttached(QObject *parent)
+ : QObject(parent), _row(-1), _column(-1), _rowspan(1), _colspan(1), _alignment(-1)
+ {
+ }
+
+ int row() const { return _row; }
+ void setRow(int r)
+ {
+ if (_row == r)
+ return;
+
+ _row = r;
+ //emit rowChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _row);
+ }
+
+ int column() const { return _column; }
+ void setColumn(int c)
+ {
+ if (_column == c)
+ return;
+
+ _column = c;
+ //emit columnChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _column);
+ }
+
+ int rowSpan() const { return _rowspan; }
+ void setRowSpan(int rs)
+ {
+ if (_rowspan == rs)
+ return;
+
+ _rowspan = rs;
+ //emit rowSpanChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _rowSpan);
+ }
+
+ int columnSpan() const { return _colspan; }
+ void setColumnSpan(int cs)
+ {
+ if (_colspan == cs)
+ return;
+
+ _colspan = cs;
+ //emit columnSpanChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _columnSpan);
+ }
+
+ Qt::Alignment alignment() const { return _alignment; }
+ void setAlignment(Qt::Alignment a)
+ {
+ if (_alignment == a)
+ return;
+
+ _alignment = a;
+ //emit alignmentChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _alignment);
+ }
+
+Q_SIGNALS:
+ //void rowChanged(QGraphicsLayoutItem*,int);
+ //void columnSpanChanged(QGraphicsLayoutItem*,int);
+ //void rowSpanChanged(QGraphicsLayoutItem*,int);
+ //void columnChanged(QGraphicsLayoutItem*,int);
+ //void alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ int _row;
+ int _column;
+ int _rowspan;
+ int _colspan;
+ Qt::Alignment _alignment;
+};
+
+QML_DEFINE_TYPE(QGraphicsGridLayoutObject,QGraphicsGridLayout)
+
+
+QGraphicsGridLayoutObject::QGraphicsGridLayoutObject(QObject *parent)
+: QObject(parent), _children(this)
+{
+}
+
+QGraphicsGridLayoutObject::~QGraphicsGridLayoutObject()
+{
+}
+
+void QGraphicsGridLayoutObject::addWidget(QGraphicsWidget *wid)
+{
+ //use attached properties
+ if (QObject *obj = attachedProperties.value(qobject_cast<QGraphicsLayoutItem*>(wid))) {
+ int row = static_cast<GridLayoutAttached *>(obj)->row();
+ int column = static_cast<GridLayoutAttached *>(obj)->column();
+ int rowSpan = static_cast<GridLayoutAttached *>(obj)->rowSpan();
+ int columnSpan = static_cast<GridLayoutAttached *>(obj)->columnSpan();
+ if (row == -1 || column == -1) {
+ qWarning() << "Must set row and column for an item in a grid layout";
+ return;
+ }
+ addItem(wid, row, column, rowSpan, columnSpan);
+ }
+}
+
+void QGraphicsGridLayoutObject::addLayoutItem(QGraphicsLayoutItem *item)
+{
+ //use attached properties
+ if (QObject *obj = attachedProperties.value(item)) {
+ int row = static_cast<GridLayoutAttached *>(obj)->row();
+ int column = static_cast<GridLayoutAttached *>(obj)->column();
+ int rowSpan = static_cast<GridLayoutAttached *>(obj)->rowSpan();
+ int columnSpan = static_cast<GridLayoutAttached *>(obj)->columnSpan();
+ Qt::Alignment alignment = static_cast<GridLayoutAttached *>(obj)->alignment();
+ if (row == -1 || column == -1) {
+ qWarning() << "Must set row and column for an item in a grid layout";
+ return;
+ }
+ addItem(item, row, column, rowSpan, columnSpan);
+ if (alignment != -1)
+ setAlignment(item,alignment);
+ }
+}
+
+//XXX is there a better way to do this?
+void QGraphicsGridLayoutObject::clearChildren()
+{
+ for (int i = 0; i < count(); ++i)
+ removeAt(i);
+}
+
+qreal QGraphicsGridLayoutObject::spacing() const
+{
+ if (verticalSpacing() == horizontalSpacing())
+ return verticalSpacing();
+ return -1; //XXX
+}
+
+QHash<QGraphicsLayoutItem*, QObject*> QGraphicsGridLayoutObject::attachedProperties;
+QObject *QGraphicsGridLayoutObject::qmlAttachedProperties(QObject *obj)
+{
+ // ### This is not allowed - you must attach to any object
+ if (!qobject_cast<QGraphicsLayoutItem*>(obj))
+ return 0;
+ GridLayoutAttached *rv = new GridLayoutAttached(obj);
+ attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv);
+ return rv;
+}
+
+QT_END_NAMESPACE
+
+#include "graphicslayouts.moc"
diff --git a/src/declarative/widgets/graphicslayouts.h b/src/declarative/widgets/graphicslayouts.h
new file mode 100644
index 0000000..303f749
--- /dev/null
+++ b/src/declarative/widgets/graphicslayouts.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHICSLAYOUTS_H
+#define GRAPHICSLAYOUTS_H
+
+#include <QtDeclarative/graphicswidgets.h>
+#include <QtGui/QGraphicsLinearLayout>
+#include <QtGui/QGraphicsGridLayout>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+QML_DECLARE_INTERFACE(QGraphicsLayoutItem)
+QML_DECLARE_INTERFACE(QGraphicsLayout)
+
+class QGraphicsLinearLayoutStretchItemObject : public QObject, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+public:
+ QGraphicsLinearLayoutStretchItemObject(QObject *parent = 0);
+
+ virtual QSizeF sizeHint(Qt::SizeHint, const QSizeF &) const;
+};
+QML_DECLARE_TYPE(QGraphicsLinearLayoutStretchItemObject)
+
+//TODO:
+// -content margins
+// -per-item spacing (does this need to be exposed?)
+// -per-item alignment
+class LinearLayoutAttached;
+class QGraphicsLinearLayoutObject : public QObject, public QGraphicsLinearLayout
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayout QGraphicsLayoutItem)
+
+ Q_PROPERTY(QmlList<QGraphicsLayoutItem *> *children READ children)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsLinearLayoutObject(QObject * = 0);
+ ~QGraphicsLinearLayoutObject();
+
+ QmlList<QGraphicsLayoutItem *> *children() { return &_children; }
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+private Q_SLOTS:
+ void updateStretch(QGraphicsLayoutItem*,int);
+ void updateAlignment(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ friend class LinearLayoutAttached;
+ void clearChildren();
+ void insertLayoutItem(int, QGraphicsLayoutItem *);
+ static QHash<QGraphicsLayoutItem*, QObject*> attachedProperties;
+
+ class ChildList : public QmlList<QGraphicsLayoutItem *>
+ {
+ public:
+ ChildList(QGraphicsLinearLayoutObject *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsLayoutItem *item)
+ {
+ insert(-1, item);
+ }
+ virtual void clear() { obj->clearChildren(); }
+ virtual int count() const { return obj->count(); }
+ virtual void removeAt(int i) { obj->removeAt(i); }
+ virtual QGraphicsLayoutItem *at(int i) const { return obj->itemAt(i); }
+ virtual void insert(int i, QGraphicsLayoutItem *item) { obj->insertLayoutItem(i, item); }
+
+ private:
+ QGraphicsLinearLayoutObject *obj;
+ };
+
+ ChildList _children;
+};
+QML_DECLARE_TYPE(QGraphicsLinearLayoutObject)
+
+//TODO:
+// -content margins
+// -column and row specific settings:
+// -alignment
+// -fixed/min/max/preferred width
+// -spacing
+// -stretch
+class QGraphicsGridLayoutObject : public QObject, public QGraphicsGridLayout
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayout QGraphicsLayoutItem)
+
+ Q_PROPERTY(QmlList<QGraphicsLayoutItem *> *children READ children)
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing)
+ Q_PROPERTY(qreal verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
+ Q_PROPERTY(qreal horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsGridLayoutObject(QObject * = 0);
+ ~QGraphicsGridLayoutObject();
+
+ QmlList<QGraphicsLayoutItem *> *children() { return &_children; }
+
+ qreal spacing() const;
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+private:
+ friend class GraphicsLayoutAttached;
+ void addWidget(QGraphicsWidget *);
+ void clearChildren();
+ void addLayoutItem(QGraphicsLayoutItem *);
+ static QHash<QGraphicsLayoutItem*, QObject*> attachedProperties;
+
+ class ChildList : public QmlList<QGraphicsLayoutItem *>
+ {
+ public:
+ ChildList(QGraphicsGridLayoutObject *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsLayoutItem *o)
+ {
+ obj->addLayoutItem(o);
+ }
+ virtual void clear() { obj->clearChildren(); }
+ virtual int count() const { return obj->count(); }
+ virtual void removeAt(int i) { obj->removeAt(i); }
+ virtual QGraphicsLayoutItem *at(int i) const { return obj->itemAt(i); }
+ //XXX GridLayout doesn't have an insert, so for now we treat it as an append.
+ // this is obviously potenitally dangerous -- perhaps should be a concrete
+ // list with no relation to layout index, etc at all.
+ virtual void insert(int, QGraphicsLayoutItem *item) { append(item); }
+
+ private:
+ QGraphicsGridLayoutObject *obj;
+ };
+
+ ChildList _children;
+};
+QML_DECLARE_TYPE(QGraphicsGridLayoutObject)
+
+#endif // GRAPHICSLAYOUTS_H
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/widgets/graphicswidgets.cpp b/src/declarative/widgets/graphicswidgets.cpp
new file mode 100644
index 0000000..86509f5
--- /dev/null
+++ b/src/declarative/widgets/graphicswidgets.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicswidgets.h"
+
+QT_BEGIN_NAMESPACE
+
+//### the single (default) property could alternatively be added to graphics view directly
+class QGraphicsViewDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QGraphicsScene *scene READ scene WRITE setScene)
+ Q_CLASSINFO("DefaultProperty", "scene")
+public:
+ QGraphicsViewDeclarativeUI(QObject *other) : QObject(other) {}
+
+ QGraphicsScene *scene() const { return static_cast<QGraphicsView *>(parent())->scene(); }
+ void setScene(QGraphicsScene *scene)
+ {
+ static_cast<QGraphicsView *>(parent())->setScene(scene);
+ }
+};
+QML_DEFINE_EXTENDED_TYPE(QGraphicsView,QGraphicsView,QGraphicsViewDeclarativeUI)
+
+class QGraphicsSceneDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QObject *> *children READ children)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsSceneDeclarativeUI(QObject *other) : QObject(other), _children(other) {}
+
+ QmlList<QObject *> *children() { return &_children; }
+
+private:
+ class Children : public QmlConcreteList<QObject *>
+ {
+ public:
+ Children(QObject *scene) : q(scene) {}
+ virtual void append(QObject *o)
+ {
+ insert(-1, o);
+ }
+ virtual void clear()
+ {
+ for (int i = 0; i < count(); ++i)
+ if (QGraphicsWidget *w = qobject_cast<QGraphicsWidget *>(at(i)))
+ static_cast<QGraphicsScene *>(q)->removeItem(w);
+ QmlConcreteList<QObject *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ if (QGraphicsWidget *w = qobject_cast<QGraphicsWidget *>(at(i)))
+ static_cast<QGraphicsScene *>(q)->removeItem(w);
+ QmlConcreteList<QObject *>::removeAt(i);
+ }
+ virtual void insert(int i, QObject *o)
+ {
+ QmlConcreteList<QObject *>::insert(i, o);
+
+ //XXX are there any cases when insertion should be different from appension?
+ if (QGraphicsWidget *w = qobject_cast<QGraphicsWidget *>(o))
+ static_cast<QGraphicsScene *>(q)->addItem(w);
+ //else if (QWidget *w = qobject_cast<QWidget *>(o))
+ // static_cast<QGraphicsScene *>(q)->addWidget(w);
+ //else
+ // qWarning() << "Can't add" << o << "to a QGraphicsScene";
+ }
+ private:
+ QObject *q;
+ };
+ Children _children;
+};
+QML_DEFINE_EXTENDED_TYPE(QGraphicsScene,QGraphicsScene,QGraphicsSceneDeclarativeUI)
+
+class QGraphicsWidgetDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QObject *> *data READ data)
+ Q_PROPERTY(QmlList<QGraphicsItem *> *children READ children)
+ Q_PROPERTY(QGraphicsLayout *layout READ layout WRITE setLayout)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsWidgetDeclarativeUI(QObject *other) : QObject(other), _widgets(this) {}
+
+ QmlList<QObject *> *data() { return &_data; }
+
+ QmlList<QGraphicsItem *> *children() { return &_widgets; }
+
+ QGraphicsLayout *layout() const { return static_cast<QGraphicsWidget *>(parent())->layout(); }
+ void setLayout(QGraphicsLayout *lo)
+ {
+ static_cast<QGraphicsWidget *>(parent())->setLayout(lo);
+ }
+
+private:
+ friend class WidgetList;
+ void setItemParent(QGraphicsItem *wid)
+ {
+ wid->setParentItem(static_cast<QGraphicsWidget *>(parent()));
+ }
+
+ //###
+ void clearWidget()
+ {
+ }
+
+ class WidgetList : public QmlConcreteList<QGraphicsItem *>
+ {
+ public:
+ WidgetList(QGraphicsWidgetDeclarativeUI *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsItem *w) { QmlConcreteList<QGraphicsItem *>::append(w); obj->setItemParent(w); }
+ virtual void clear() { QmlConcreteList<QGraphicsItem *>::clear(); obj->clearWidget(); }
+ virtual void removeAt(int i) { QmlConcreteList<QGraphicsItem *>::removeAt(i); } //XXX
+ virtual void insert(int i, QGraphicsItem *item) { QmlConcreteList<QGraphicsItem *>::insert(i, item); obj->setItemParent(item); }
+
+ private:
+ QGraphicsWidgetDeclarativeUI *obj;
+ };
+ WidgetList _widgets;
+ QmlConcreteList<QObject *> _data;
+};
+
+QML_DEFINE_EXTENDED_TYPE(QGraphicsWidget,QGraphicsWidget,QGraphicsWidgetDeclarativeUI)
+
+QML_DEFINE_INTERFACE(QGraphicsItem)
+
+#include "graphicswidgets.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/widgets/graphicswidgets.h b/src/declarative/widgets/graphicswidgets.h
new file mode 100644
index 0000000..e29f1d6
--- /dev/null
+++ b/src/declarative/widgets/graphicswidgets.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHICSWIDGETS_H
+#define GRAPHICSWIDGETS_H
+
+#include <QtDeclarative/qml.h>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QGraphicsView>
+#include <QtGui/QGraphicsWidget>
+#include <QtGui/QGraphicsItem>
+
+QT_BEGIN_NAMESPACE
+
+QML_DECLARE_TYPE(QGraphicsView)
+QML_DECLARE_TYPE_HASMETATYPE(QGraphicsScene)
+QML_DECLARE_TYPE(QGraphicsWidget)
+QML_DECLARE_INTERFACE_HASMETATYPE(QGraphicsItem)
+
+QT_END_NAMESPACE
+
+#endif // GRAPHICSWIDGETS_H
diff --git a/src/declarative/widgets/widgets.pri b/src/declarative/widgets/widgets.pri
new file mode 100644
index 0000000..41c50d8
--- /dev/null
+++ b/src/declarative/widgets/widgets.pri
@@ -0,0 +1,10 @@
+SOURCES += \
+ widgets/graphicswidgets.cpp \
+ widgets/graphicslayouts.cpp \
+
+HEADERS += \
+ widgets/graphicswidgets.h \
+ widgets/graphicslayouts.h \
+
+
+
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index f6ee197..e398dcf 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -436,6 +436,7 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags)
+Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem")
inline void QGraphicsItem::setPos(qreal ax, qreal ay)
{ setPos(QPointF(ax, ay)); }
diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h
index fad6c3bb..a5f2884 100644
--- a/src/gui/graphicsview/qgraphicslayout.h
+++ b/src/gui/graphicsview/qgraphicslayout.h
@@ -85,6 +85,8 @@ private:
friend class QGraphicsWidget;
};
+Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout")
+
#endif
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h
index 31f5d90..0ff3acc 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem.h
@@ -121,6 +121,8 @@ private:
friend class QGraphicsLayout;
};
+Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem")
+
inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah)
{ setMinimumSize(QSizeF(aw, ah)); }
inline void QGraphicsLayoutItem::setPreferredSize(qreal aw, qreal ah)
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 3296aee..8d6d880 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -170,14 +170,54 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \property QGraphicsWidget::enabled
- \brief whether the item is enabled or not
+ \property QGraphicsWidget::xScale
+ \brief the x scale factor
- This property is declared in QGraphicsItem.
+ This property is declared in QGraphicsItem.
+ \sa QGraphicsItem::xScale(), QGraphicsItem::setXScale()
+ */
- By default, this property is true.
+/*!
+ \property QGraphicsWidget::yScale
+ \brief the y scale factor
+
+ This property is declared in QGraphicsItem.
+ \sa QGraphicsItem::yScale(), QGraphicsItem::setYScale()
+*/
+
+/*!
+ \property QGraphicsWidget::zRotation
+ \brief the z rotation angle
+
+ This property is declared in QGraphicsItem.
+ \sa QGraphicsItem::zRotation(), QGraphicsItem::setZRotation()
+*/
+
+/*!
+ \property QGraphicsWidget::xRotation
+ \brief the x rotation angle
+
+ This property is declared in QGraphicsItem.
+ \sa QGraphicsItem::xRotation(), QGraphicsItem::setXRotation()
+*/
+
+/*!
+ \property QGraphicsWidget::yRotation
+ \brief the y rotation angle.
+
+ This property is declared in QGraphicsItem.
+ \sa QGraphicsItem::yRotation(), QGraphicsItem::setYRotation()
+*/
+
+/*!
+ \property QGraphicsWidget::enabled
+ \brief whether the item is enabled or not
+
+ This property is declared in QGraphicsItem.
+
+ By default, this property is true.
- \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
+ \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
*/
/*!
@@ -339,7 +379,7 @@ QGraphicsWidget::~QGraphicsWidget()
//we check if we have a layout previously
if (d->layout) {
- delete d->layout;
+ QGraphicsLayout *temp = d->layout;
foreach (QGraphicsItem * item, childItems()) {
// In case of a custom layout which doesn't remove and delete items, we ensure that
// the parent layout item does not point to the deleted layout. This code is here to
@@ -350,6 +390,8 @@ QGraphicsWidget::~QGraphicsWidget()
widget->setParentLayoutItem(0);
}
}
+ d->layout = 0;
+ delete temp;
}
// Remove this graphics widget from widgetStyles
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index a5c9068..1a835df 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -69,6 +69,7 @@ class QGraphicsWidgetPrivate;
class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, public QGraphicsLayoutItem
{
Q_OBJECT
+ Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem)
Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
index d7bf8c3..ffc6fe8 100644
--- a/src/gui/kernel/qaction.h
+++ b/src/gui/kernel/qaction.h
@@ -67,24 +67,24 @@ class Q_GUI_EXPORT QAction : public QObject
Q_DECLARE_PRIVATE(QAction)
Q_ENUMS(MenuRole)
- Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable)
+ Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed)
Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
- Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
- Q_PROPERTY(QString text READ text WRITE setText)
- Q_PROPERTY(QString iconText READ iconText WRITE setIconText)
- Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
- Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
- Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
- Q_PROPERTY(QFont font READ font WRITE setFont)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed)
+ Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed)
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed)
+ Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed)
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed)
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed)
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
#ifndef QT_NO_SHORTCUT
- Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
- Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext)
- Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
+ Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed)
+ Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed)
+ Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed)
#endif
- Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
- Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole)
- Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
+ Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
+ Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
public:
enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index a59e870..8c8911e 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -49,6 +49,7 @@
#include "qmime.h"
#include "qdnd_p.h"
#include "qevent_p.h"
+#include "qdatetime.h"
QT_BEGIN_NAMESPACE
@@ -226,6 +227,17 @@ QMouseEvent *QMouseEvent::createExtendedMouseEvent(Type type, const QPointF &pos
}
/*!
+ \internal
+*/
+QMouseEvent *QMouseEvent::createExtendedMouseEvent(Type type, const QPointF &pos,
+ const QPoint &globalPos, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ const QDateTime &eventTime)
+{
+ return new QMouseEventEx(type, pos, globalPos, button, buttons, modifiers, eventTime);
+}
+
+/*!
\fn bool QMouseEvent::hasExtendedInfo() const
\internal
*/
@@ -247,13 +259,40 @@ QPointF QMouseEvent::posF() const
return hasExtendedInfo() ? reinterpret_cast<const QMouseEventEx *>(this)->posF : QPointF(pos());
}
+/*!
+ \since 4.6
+
+ Returns the time the mouse event occurred. On many systems and platforms
+ this is equivalent to QDateTime::currentDateTime().
+*/
+QDateTime QMouseEvent::eventDateTime() const
+{
+ if(hasExtendedInfo() && reinterpret_cast<const QMouseEventEx *>(this)->timeSet) {
+ return reinterpret_cast<const QMouseEventEx *>(this)->time;
+ } else {
+ return QDateTime::currentDateTime();
+ }
+}
+
/*!
\internal
*/
QMouseEventEx::QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers)
- : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos)
+ : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos), timeSet(false)
+{
+ d = reinterpret_cast<QEventPrivate *>(this);
+}
+
+/*!
+ \internal
+*/
+QMouseEventEx::QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers,
+ const QDateTime &eventTime)
+ : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos), timeSet(true), time(eventTime)
{
d = reinterpret_cast<QEventPrivate *>(this);
}
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 449730d..150e139 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -93,8 +93,13 @@ public:
static QMouseEvent *createExtendedMouseEvent(Type type, const QPointF &pos,
const QPoint &globalPos, Qt::MouseButton button,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ static QMouseEvent *createExtendedMouseEvent(Type type, const QPointF &pos,
+ const QPoint &globalPos, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ const QDateTime &eventTime);
inline bool hasExtendedInfo() const { return reinterpret_cast<const QMouseEvent *>(d) == this; }
QPointF posF() const;
+ QDateTime eventDateTime() const;
#ifdef QT3_SUPPORT
QT3_SUPPORT_CONSTRUCTOR QMouseEvent(Type type, const QPoint &pos, Qt::ButtonState button, int state);
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 8e762d6..484f335 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -43,6 +43,7 @@
#define QEVENT_P_H
#include <QtCore/qglobal.h>
+#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
@@ -82,10 +83,15 @@ public:
QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers);
+ QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers, const QDateTime &eventTime);
~QMouseEventEx();
protected:
QPointF posF;
+ bool timeSet:1;
+ QDateTime time;
friend class QMouseEvent;
};
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index d436ffb..d03d2df 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -5861,7 +5861,7 @@ QWidget *QWidget::focusWidget() const
/*!
Returns the next widget in this widget's focus chain.
- \sa previousInFocusChain
+ \sa previousInFocusChain()
*/
QWidget *QWidget::nextInFocusChain() const
{
@@ -5871,7 +5871,7 @@ QWidget *QWidget::nextInFocusChain() const
/*!
Returns the previous widget in this widget's focus chain.
- \sa nextInFocusChain
+ \sa nextInFocusChain()
\since 4.6
*/
diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp
index 6ecd878..61df367 100644
--- a/src/gui/math3d/qgenericmatrix.cpp
+++ b/src/gui/math3d/qgenericmatrix.cpp
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
But they can be different if the user wants to store elements
internally in a fixed-point format for the underlying hardware.
- \sa QMatrix4x4, QFixedPt
+ \sa QMatrix4x4
*/
/*!
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index bbe1a76..4cf695e 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6958,11 +6958,11 @@ void qt_build_pow_tables() {
#endif
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
- const qreal gray_gamma = 2.31;
+ const qreal gray_gamma = qreal(2.31);
for (int i=0; i<256; ++i)
qt_pow_gamma[i] = uint(qRound(pow(i / qreal(255.), gray_gamma) * 2047));
for (int i=0; i<2048; ++i)
- qt_pow_invgamma[i] = uchar(qRound(pow(i / 2047.0, 1 / gray_gamma) * 255));
+ qt_pow_invgamma[i] = uchar(qRound(pow(i / qreal(2047.), 1 / gray_gamma) * 255));
#endif
}
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index 230d30b..f4acd5f 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1039,28 +1039,58 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
#endif
/*!
- \struct QMargins
+ \class QMargins
\since 4.6
Holds the borders used to split a pixmap into nine segments in order to
draw it, similar to \l{http://www.w3.org/TR/css3-background/}
{CSS3 border-images}.
- \sa qDrawBorderPixmap, Qt::TileRule, QTileRules
+ \sa qDrawBorderPixmap(), Qt::TileRule, QTileRules
*/
/*!
- \struct QTileRules
+ \fn QMargins::QMargins(int margin)
+
+ Constructs an instance of QMargins setting all four
+ margins to \a margin.
+ */
+
+/*!
+ \fn QMargins::QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin)
+
+ Constructs an instance of QMargins setting the four
+ margins to \a topMargin, \a leftMargin, \a bottomMargin,
+ and \a rightMargin.
+ */
+
+/*!
+ \class QTileRules
\since 4.6
Holds the rules used to draw a pixmap or image split into nine segments,
similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}.
- \sa qDrawBorderPixmap, Qt::TileRule, QMargins
+ \sa qDrawBorderPixmap(), Qt::TileRule, QMargins
+*/
+
+/*!
+ \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
+
+ Constructs an instance of QTileRules from the \a horizontalRule
+ and the \a verticalRule.
+*/
+
+/*!
+ \fn QTileRules::QTileRules(Qt::TileRule rule)
+
+ Constructs an instance of QTileRules setting both the
+ horizontal and vertical rules to \a rule.
*/
/*!
\fn qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
+ \relates QMargins
\since 4.6
Draws the given \a pixmap into the given \a target rectangle, using the
@@ -1150,6 +1180,7 @@ static inline void qDrawHorizontallyRoundedPixmap(QPainter *painter, const QRect
/*!
\since 4.6
+ \relates QMargins
Draws the indicated \a sourceRect rectangle from the given \a pixmap into
the given \a targetRect rectangle, using the given \a painter. The pixmap
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index bd91dfc..e2cd7a3 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -2049,7 +2049,7 @@ QPainterPath QPainterPath::translated(qreal dx, qreal dy) const
}
/*!
- \fn void QPainterPath::translated(const QPointF &offset)
+ \fn void QPainterPath::translated(const QPointF &offset) const
\overload
\since 4.6
diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp
index 3fab682..45be9a8 100644
--- a/src/gui/styles/qstyle.cpp
+++ b/src/gui/styles/qstyle.cpp
@@ -1179,6 +1179,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SC_All Special value that matches all sub-controls.
\omitvalue SC_Q3ListViewBranch
+ \omitvalue SC_CustomBase
\sa ComplexControl
*/
diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h
index 4dac4f7..e50540a 100644
--- a/src/gui/text/qtextcontrol_p.h
+++ b/src/gui/text/qtextcontrol_p.h
@@ -83,7 +83,7 @@ class QAbstractScrollArea;
class QEvent;
class QTimerEvent;
-class Q_AUTOTEST_EXPORT QTextControl : public QObject
+class Q_GUI_EXPORT QTextControl : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QTextControl)
diff --git a/src/gui/widgets/qbuttongroup.cpp b/src/gui/widgets/qbuttongroup.cpp
index ebfafe3..8da97bb 100644
--- a/src/gui/widgets/qbuttongroup.cpp
+++ b/src/gui/widgets/qbuttongroup.cpp
@@ -178,10 +178,11 @@
/*!
\fn void QButtonGroup::addButton(QAbstractButton *button);
- Adds the given \a button to the end of the group's internal list of buttons.
- An \a id will be assigned to the button by this QButtonGroup. Automatically
- assigned ids are guaranteed to be negative, starting with -2. If you are also
- assigning your own ids, use positive values to avoid conflicts.
+ Adds the given \a button to the end of the group's internal list
+ of buttons. An id will be assigned to the button by this
+ QButtonGroup. Automatically assigned ids are guaranteed to be
+ negative, starting with -2. If you are also assigning your own
+ ids, use positive values to avoid conflicts.
\sa removeButton() buttons()
*/
@@ -189,8 +190,8 @@
/*!
\fn void QButtonGroup::addButton(QAbstractButton *button, int id);
- Adds the given \a button to the button group, with the given \a
- id. It is recommended to assign only positive ids.
+ Adds the given \a button to the button group, with the given
+ \a id. It is recommended to assign only positive ids.
\sa removeButton() buttons()
*/
diff --git a/src/script/qscriptextqobject.cpp b/src/script/qscriptextqobject.cpp
index 4522807..802653a 100644
--- a/src/script/qscriptextqobject.cpp
+++ b/src/script/qscriptextqobject.cpp
@@ -736,7 +736,7 @@ static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType
meta->static_metacall(QMetaObject::CreateInstance, chosenIndex, params);
} else {
Q_ASSERT(thisQObject != 0);
- thisQObject->qt_metacall(QMetaObject::InvokeMetaMethod, chosenIndex, params);
+ QMetaObject::metacall(thisQObject, QMetaObject::InvokeMetaMethod, chosenIndex, params);
}
if (scriptable)
diff --git a/src/src.pro b/src/src.pro
index f40c6ad..e35c3f5 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -27,6 +27,7 @@ contains(QT_CONFIG, webkit) {
SRC_SUBDIRS += src_webkit
}
contains(QT_CONFIG, scripttools): SRC_SUBDIRS += src_scripttools
+contains(QT_CONFIG, declarative): SRC_SUBDIRS += src_declarative
SRC_SUBDIRS += src_plugins
src_winmain.subdir = $$QT_SOURCE_TREE/src/winmain
@@ -79,6 +80,8 @@ src_javascriptcore.subdir = $$QT_SOURCE_TREE/src/3rdparty/webkit/JavaScriptCore
src_javascriptcore.target = sub-javascriptcore
src_webkit.subdir = $$QT_SOURCE_TREE/src/3rdparty/webkit/WebCore
src_webkit.target = sub-webkit
+src_declarative.subdir = $$QT_SOURCE_TREE/src/declarative
+src_declarative.target = sub-declarative
#CONFIG += ordered
!wince*:!ordered {
@@ -103,6 +106,7 @@ src_webkit.target = sub-webkit
src_tools_uic3.depends = src_qt3support src_xml
src_tools_idc.depends = src_corelib
src_tools_activeqt.depends = src_tools_idc src_gui
+ src_declarative.depends = src_xml src_gui src_script src_network src_svg
src_plugins.depends = src_gui src_sql src_svg
contains(QT_CONFIG, webkit) {
src_webkit.depends = src_gui src_sql src_network src_xml
diff --git a/src/testlib/qtestelementattribute.cpp b/src/testlib/qtestelementattribute.cpp
index 540389b..1a13de9 100644
--- a/src/testlib/qtestelementattribute.cpp
+++ b/src/testlib/qtestelementattribute.cpp
@@ -113,5 +113,45 @@ bool QTestElementAttribute::setPair(QTest::AttributeIndex index, const char *val
return (attributeValue!=0) ? true:false;
}
+/*!
+ \enum QTest::AttributeIndex
+
+ \relates QTestElementAttribute
+
+ \value AI_Undefined
+ \value AI_Name
+ \value AI_Result
+ \value AI_Tests
+ \value AI_Failures
+ \value AI_Errors
+ \value AI_Type
+ \value AI_Description
+ \value AI_PropertyValue
+ \value AI_QTestVersion
+ \value AI_QtVersion
+ \value AI_File
+ \value AI_Line
+ \value AI_Metric
+ \value AI_Tag
+ \value AI_Value
+ \value AI_Iterations
+*/
+
+/*!
+ \enum QTest::LogElementType
+
+ \relates QTestElementAttribute
+
+ \value LET_Undefined
+ \value LET_Property
+ \value LET_Properties
+ \value LET_Failure
+ \value LET_Error
+ \value LET_TestCase
+ \value LET_TestSuite
+ \value LET_Benchmark
+ \value LET_SystemError
+*/
+
QT_END_NAMESPACE
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index e94bb77..b6bd1ad 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -66,7 +66,8 @@ enum PropertyFlags {
ResolveEditable = 0x00080000,
User = 0x00100000,
ResolveUser = 0x00200000,
- Notify = 0x00400000
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
};
enum MethodFlags {
AccessPrivate = 0x00,
@@ -194,10 +195,10 @@ void Generator::generateCode()
QByteArray qualifiedClassNameIdentifier = cdef->qualified;
qualifiedClassNameIdentifier.replace(':', '_');
- int index = 12;
+ int index = 13;
fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
fprintf(out, "\n // content:\n");
- fprintf(out, " %4d, // revision\n", 2);
+ fprintf(out, " %4d, // revision\n", 3);
fprintf(out, " %4d, // classname\n", strreg(cdef->qualified));
fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0);
index += cdef->classInfoList.count() * 2;
@@ -217,6 +218,9 @@ void Generator::generateCode()
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
isConstructible ? index : 0);
+ fprintf(out, " %4d, // flags\n", 0);
+
+
//
// Build classinfo array
//
@@ -371,7 +375,7 @@ void Generator::generateCode()
if (isQt || !cdef->hasQObject)
return;
- fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return &staticMetaObject;\n}\n",
+ fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;\n}\n",
cdef->qualified.constData());
//
// Generate smart cast function
@@ -394,8 +398,8 @@ void Generator::generateCode()
fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData());
for (int k = j; k >= 0; --k)
fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData());
- fprintf(out, "const_cast< %s*>(this)%s;\n",
- cdef->classname.constData(), QByteArray(j+1, ')').constData());
+ fprintf(out, "%sconst_cast< %s*>(this)%s;\n",
+ (iface.at(j).isCast?"*":""), cdef->classname.constData(), QByteArray(j+1, ')').constData());
}
}
if (!purestSuperClass.isEmpty() && !isQObject) {
@@ -754,6 +758,9 @@ void Generator::generateMetacall()
else if (cdef->enumDeclarations.value(p.type, false))
fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s()); break;\n",
propindex, p.read.constData());
+ else if (p.type == "qreal")
+ fprintf(out, " case %d: *reinterpret_cast< double*>(_v) = %s(); break;\n",
+ propindex, p.read.constData());
else
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s(); break;\n",
propindex, p.type.constData(), p.read.constData());
@@ -778,6 +785,9 @@ void Generator::generateMetacall()
if (cdef->enumDeclarations.value(p.type, false)) {
fprintf(out, " case %d: %s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
propindex, p.write.constData());
+ } else if(p.type == "qreal") {
+ fprintf(out, " case %d: %s(*reinterpret_cast< double*>(_v)); break;\n",
+ propindex, p.write.constData());
} else {
fprintf(out, " case %d: %s(*reinterpret_cast< %s*>(_v)); break;\n",
propindex, p.write.constData(), p.type.constData());
diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp
index 2a4fbf9..62c16ee 100644
--- a/src/tools/moc/keywords.cpp
+++ b/src/tools/moc/keywords.cpp
@@ -43,12 +43,12 @@
// DO NOT EDIT.
static const short keyword_trans[][128] = {
- {0,0,0,0,0,0,0,0,0,525,522,0,0,0,0,0,
+ {0,0,0,0,0,0,0,0,0,539,536,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 525,252,523,526,0,38,239,524,25,26,236,234,30,235,27,237,
+ 539,252,537,540,0,38,239,538,25,26,236,234,30,235,27,237,
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,21,8,8,8,8,8,8,8,8,8,31,527,32,238,8,
+ 8,21,8,8,8,8,8,8,8,8,8,31,541,32,238,8,
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -129,7 +129,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,290,222,0,0,461,0,0,0,
+ 0,0,0,0,0,0,0,0,290,222,0,0,475,0,0,0,
0,0,0,0,55,0,0,330,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -168,7 +168,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,485,0,0,0,0,0,0,0,0,0,0,357,
+ 0,0,0,0,499,0,0,0,0,0,0,0,0,0,0,357,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -190,7 +190,7 @@ static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
- 530,530,530,530,530,530,530,530,530,530,0,0,0,0,0,0,
+ 544,544,544,544,544,544,544,544,544,544,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -349,7 +349,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,528,
+ 0,0,0,0,0,0,0,0,0,0,543,0,0,0,0,542,
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -385,7 +385,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,458,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
+ 0,472,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -399,7 +399,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,475,0,0,0,0,0,372,
+ 0,0,0,0,0,0,0,0,0,489,0,0,0,0,0,372,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -415,7 +415,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,513,0,437,0,0,0,465,0,0,471,0,0,0,
+ 0,0,0,527,0,437,0,0,0,479,0,0,485,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -423,16 +423,24 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,458,0,0,0,0,0,0,0,0,0,0,440,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,450,0,506,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,497,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,486,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,450,0,520,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,511,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,500,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
@@ -884,7 +892,7 @@ static const struct
{CHARACTER, 46, 0, 0, CHARACTER},
{CHARACTER, 0, 84, 438, CHARACTER},
{CHARACTER, 0, 83, 387, CHARACTER},
- {CHARACTER, 0, 76, 440, CHARACTER},
+ {CHARACTER, 47, 0, 0, CHARACTER},
{CHARACTER, 0, 65, 441, CHARACTER},
{CHARACTER, 0, 83, 442, CHARACTER},
{CHARACTER, 0, 83, 443, CHARACTER},
@@ -894,7 +902,7 @@ static const struct
{CHARACTER, 0, 79, 447, CHARACTER},
{Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 78, 449, CHARACTER},
- {CHARACTER, 47, 0, 0, CHARACTER},
+ {CHARACTER, 48, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 451, CHARACTER},
{CHARACTER, 0, 82, 452, CHARACTER},
{CHARACTER, 0, 70, 453, CHARACTER},
@@ -903,69 +911,83 @@ static const struct
{CHARACTER, 0, 69, 456, CHARACTER},
{CHARACTER, 0, 83, 457, CHARACTER},
{Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 108, 459, CHARACTER},
- {CHARACTER, 0, 115, 460, CHARACTER},
+ {CHARACTER, 0, 83, 459, CHARACTER},
+ {CHARACTER, 0, 84, 460, CHARACTER},
+ {CHARACTER, 0, 95, 461, CHARACTER},
+ {CHARACTER, 0, 73, 462, CHARACTER},
+ {CHARACTER, 0, 78, 463, CHARACTER},
+ {CHARACTER, 0, 84, 464, CHARACTER},
+ {CHARACTER, 0, 69, 465, CHARACTER},
+ {CHARACTER, 0, 82, 466, CHARACTER},
+ {CHARACTER, 0, 70, 467, CHARACTER},
+ {CHARACTER, 0, 65, 468, CHARACTER},
+ {CHARACTER, 0, 67, 469, CHARACTER},
+ {CHARACTER, 0, 69, 470, CHARACTER},
+ {CHARACTER, 0, 83, 471, CHARACTER},
+ {Q_CAST_INTERFACES_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 108, 473, CHARACTER},
+ {CHARACTER, 0, 115, 474, CHARACTER},
{SIGNALS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 111, 462, CHARACTER},
- {CHARACTER, 0, 116, 463, CHARACTER},
- {CHARACTER, 0, 115, 464, CHARACTER},
+ {CHARACTER, 0, 111, 476, CHARACTER},
+ {CHARACTER, 0, 116, 477, CHARACTER},
+ {CHARACTER, 0, 115, 478, CHARACTER},
{SLOTS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 71, 466, CHARACTER},
- {CHARACTER, 0, 78, 467, CHARACTER},
- {CHARACTER, 0, 65, 468, CHARACTER},
- {CHARACTER, 0, 76, 469, CHARACTER},
- {Q_SIGNAL_TOKEN, 0, 83, 470, CHARACTER},
+ {CHARACTER, 0, 71, 480, CHARACTER},
+ {CHARACTER, 0, 78, 481, CHARACTER},
+ {CHARACTER, 0, 65, 482, CHARACTER},
+ {CHARACTER, 0, 76, 483, CHARACTER},
+ {Q_SIGNAL_TOKEN, 0, 83, 484, CHARACTER},
{Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 472, CHARACTER},
- {CHARACTER, 0, 84, 473, CHARACTER},
- {Q_SLOT_TOKEN, 0, 83, 474, CHARACTER},
+ {CHARACTER, 0, 79, 486, CHARACTER},
+ {CHARACTER, 0, 84, 487, CHARACTER},
+ {Q_SLOT_TOKEN, 0, 83, 488, CHARACTER},
{Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 86, 476, CHARACTER},
- {CHARACTER, 0, 65, 477, CHARACTER},
- {CHARACTER, 0, 84, 478, CHARACTER},
- {CHARACTER, 0, 69, 479, CHARACTER},
- {CHARACTER, 0, 95, 480, CHARACTER},
- {CHARACTER, 0, 83, 481, CHARACTER},
- {CHARACTER, 0, 76, 482, CHARACTER},
- {CHARACTER, 0, 79, 483, CHARACTER},
- {CHARACTER, 0, 84, 484, CHARACTER},
+ {CHARACTER, 0, 86, 490, CHARACTER},
+ {CHARACTER, 0, 65, 491, CHARACTER},
+ {CHARACTER, 0, 84, 492, CHARACTER},
+ {CHARACTER, 0, 69, 493, CHARACTER},
+ {CHARACTER, 0, 95, 494, CHARACTER},
+ {CHARACTER, 0, 83, 495, CHARACTER},
+ {CHARACTER, 0, 76, 496, CHARACTER},
+ {CHARACTER, 0, 79, 497, CHARACTER},
+ {CHARACTER, 0, 84, 498, CHARACTER},
{Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 48, 0, 0, CHARACTER},
- {CHARACTER, 0, 77, 487, CHARACTER},
- {CHARACTER, 0, 79, 488, CHARACTER},
- {CHARACTER, 0, 67, 489, CHARACTER},
- {CHARACTER, 0, 95, 490, CHARACTER},
- {CHARACTER, 0, 67, 491, CHARACTER},
- {CHARACTER, 0, 79, 492, CHARACTER},
- {CHARACTER, 0, 77, 493, CHARACTER},
- {CHARACTER, 0, 80, 494, CHARACTER},
- {CHARACTER, 0, 65, 495, CHARACTER},
- {CHARACTER, 0, 84, 496, CHARACTER},
+ {CHARACTER, 49, 0, 0, CHARACTER},
+ {CHARACTER, 0, 77, 501, CHARACTER},
+ {CHARACTER, 0, 79, 502, CHARACTER},
+ {CHARACTER, 0, 67, 503, CHARACTER},
+ {CHARACTER, 0, 95, 504, CHARACTER},
+ {CHARACTER, 0, 67, 505, CHARACTER},
+ {CHARACTER, 0, 79, 506, CHARACTER},
+ {CHARACTER, 0, 77, 507, CHARACTER},
+ {CHARACTER, 0, 80, 508, CHARACTER},
+ {CHARACTER, 0, 65, 509, CHARACTER},
+ {CHARACTER, 0, 84, 510, CHARACTER},
{Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 95, 498, CHARACTER},
- {CHARACTER, 0, 83, 499, CHARACTER},
- {CHARACTER, 0, 85, 500, CHARACTER},
- {CHARACTER, 0, 80, 501, CHARACTER},
- {CHARACTER, 0, 80, 502, CHARACTER},
- {CHARACTER, 0, 79, 503, CHARACTER},
- {CHARACTER, 0, 82, 504, CHARACTER},
- {CHARACTER, 0, 84, 505, CHARACTER},
+ {CHARACTER, 0, 95, 512, CHARACTER},
+ {CHARACTER, 0, 83, 513, CHARACTER},
+ {CHARACTER, 0, 85, 514, CHARACTER},
+ {CHARACTER, 0, 80, 515, CHARACTER},
+ {CHARACTER, 0, 80, 516, CHARACTER},
+ {CHARACTER, 0, 79, 517, CHARACTER},
+ {CHARACTER, 0, 82, 518, CHARACTER},
+ {CHARACTER, 0, 84, 519, CHARACTER},
{Q_QT3_SUPPORT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 507, CHARACTER},
- {CHARACTER, 0, 75, 508, CHARACTER},
- {CHARACTER, 0, 65, 509, CHARACTER},
- {CHARACTER, 0, 66, 510, CHARACTER},
- {CHARACTER, 0, 76, 511, CHARACTER},
- {CHARACTER, 0, 69, 512, CHARACTER},
+ {CHARACTER, 0, 79, 521, CHARACTER},
+ {CHARACTER, 0, 75, 522, CHARACTER},
+ {CHARACTER, 0, 65, 523, CHARACTER},
+ {CHARACTER, 0, 66, 524, CHARACTER},
+ {CHARACTER, 0, 76, 525, CHARACTER},
+ {CHARACTER, 0, 69, 526, CHARACTER},
{Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 82, 514, CHARACTER},
- {CHARACTER, 0, 73, 515, CHARACTER},
- {CHARACTER, 0, 80, 516, CHARACTER},
- {CHARACTER, 0, 84, 517, CHARACTER},
- {CHARACTER, 0, 65, 518, CHARACTER},
- {CHARACTER, 0, 66, 519, CHARACTER},
- {CHARACTER, 0, 76, 520, CHARACTER},
- {CHARACTER, 0, 69, 521, CHARACTER},
+ {CHARACTER, 0, 82, 528, CHARACTER},
+ {CHARACTER, 0, 73, 529, CHARACTER},
+ {CHARACTER, 0, 80, 530, CHARACTER},
+ {CHARACTER, 0, 84, 531, CHARACTER},
+ {CHARACTER, 0, 65, 532, CHARACTER},
+ {CHARACTER, 0, 66, 533, CHARACTER},
+ {CHARACTER, 0, 76, 534, CHARACTER},
+ {CHARACTER, 0, 69, 535, CHARACTER},
{Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER},
{NEWLINE, 0, 0, 0, NOTOKEN},
{QUOTE, 0, 0, 0, NOTOKEN},
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 8ca2823..72ed7af 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -654,8 +654,11 @@ void Moc::parse()
case Q_CLASSINFO_TOKEN:
parseClassInfo(&def);
break;
+ case Q_CAST_INTERFACES_TOKEN:
+ parseInterfaces(&def, true);
+ break;
case Q_INTERFACES_TOKEN:
- parseInterfaces(&def);
+ parseInterfaces(&def, false);
break;
case Q_PRIVATE_SLOT_TOKEN:
parseSlotInPrivate(&def, access);
@@ -1025,12 +1028,12 @@ void Moc::parseClassInfo(ClassDef *def)
def->classInfoList += infoDef;
}
-void Moc::parseInterfaces(ClassDef *def)
+void Moc::parseInterfaces(ClassDef *def, bool isCast)
{
next(LPAREN);
while (test(IDENTIFIER)) {
QList<ClassDef::Interface> iface;
- iface += ClassDef::Interface(lexem());
+ iface += ClassDef::Interface(lexem(), isCast);
while (test(SCOPE)) {
iface.last().className += lexem();
next(IDENTIFIER);
@@ -1038,7 +1041,7 @@ void Moc::parseInterfaces(ClassDef *def)
}
while (test(COLON)) {
next(IDENTIFIER);
- iface += ClassDef::Interface(lexem());
+ iface += ClassDef::Interface(lexem(), isCast);
while (test(SCOPE)) {
iface.last().className += lexem();
next(IDENTIFIER);
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 689104c..c02864a 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -144,10 +144,11 @@ struct ClassDef {
struct Interface
{
- inline explicit Interface(const QByteArray &_className)
- : className(_className) {}
+ inline explicit Interface(const QByteArray &_className, bool _isCast)
+ : className(_className), isCast(_isCast) {}
QByteArray className;
QByteArray interfaceId;
+ bool isCast;
};
QList<QList<Interface> >interfaceList;
@@ -217,7 +218,7 @@ public:
void parseEnumOrFlag(ClassDef *def, bool isFlag);
void parseFlag(ClassDef *def);
void parseClassInfo(ClassDef *def);
- void parseInterfaces(ClassDef *def);
+ void parseInterfaces(ClassDef *def, bool isCast);
void parseDeclareInterface();
void parseDeclareMetatype();
void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access);
diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h
index 13c9a1d..7734a63 100644
--- a/src/tools/moc/token.h
+++ b/src/tools/moc/token.h
@@ -176,6 +176,7 @@ enum Token {
Q_DECLARE_METATYPE_TOKEN,
Q_CLASSINFO_TOKEN,
Q_INTERFACES_TOKEN,
+ Q_CAST_INTERFACES_TOKEN,
Q_SIGNALS_TOKEN,
Q_SLOTS_TOKEN,
Q_SIGNAL_TOKEN,
diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp
index 116be2b..a1a8215 100644
--- a/src/tools/moc/util/generate_keywords.cpp
+++ b/src/tools/moc/util/generate_keywords.cpp
@@ -237,6 +237,7 @@ static const Keyword keywords[] = {
{ "Q_SETS", "Q_FLAGS_TOKEN" },
{ "Q_CLASSINFO", "Q_CLASSINFO_TOKEN" },
{ "Q_INTERFACES", "Q_INTERFACES_TOKEN" },
+ { "Q_CAST_INTERFACES", "Q_CAST_INTERFACES_TOKEN" },
{ "signals", "SIGNALS" },
{ "slots", "SLOTS" },
{ "Q_SIGNALS", "Q_SIGNALS_TOKEN" },
diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
index 4a5c219..9bd4425 100644
--- a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
+++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
@@ -111,7 +111,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
networkLoop.connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
networkLoop.connect(reply, SIGNAL(finished()), SLOT(finished()));
- if(networkLoop.exec())
+ if(networkLoop.exec(QEventLoop::ExcludeUserInputEvents))
{
const QString errorMessage(escape(reply->errorString()));
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index a65c172..c1bf2f4 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -6,9 +6,11 @@ TEMPLATE = subdirs
SUBDIRS += _networkselftest \
bic \
+ dynamicobject \
collections \
compile \
compilerwarnings \
+ dynamicobject \
exceptionsafety \
macgui \
macplist \
@@ -441,3 +443,5 @@ contains(QT_CONFIG, webkit): SUBDIRS += \
qwebpage
SUBDIRS += math3d
+
+contains(QT_CONFIG, declarative): SUBDIRS += declarative
diff --git a/tests/auto/declarative/.gitignore b/tests/auto/declarative/.gitignore
new file mode 100644
index 0000000..c8bbd2f
--- /dev/null
+++ b/tests/auto/declarative/.gitignore
@@ -0,0 +1,3 @@
+tst_*
+!tst_*.*
+tst_*~
diff --git a/tests/auto/declarative/anchors/anchors.pro b/tests/auto/declarative/anchors/anchors.pro
new file mode 100644
index 0000000..7b22cfb
--- /dev/null
+++ b/tests/auto/declarative/anchors/anchors.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_anchors.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/anchors/data/anchors.qml b/tests/auto/declarative/anchors/data/anchors.qml
new file mode 100644
index 0000000..6a87390
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/anchors.qml
@@ -0,0 +1,115 @@
+Rect {
+ color: "white"
+ width: 240
+ height: 320
+ Rect { id: MasterRect; x: 26; width: 96; height: 20; color: "red" }
+ Rect {
+ id: Rect1
+ y: 20; width: 10; height: 10
+ anchors.left: MasterRect.left
+ }
+ Rect {
+ id: Rect2
+ y: 20; width: 10; height: 10
+ anchors.left: MasterRect.right
+ }
+ Rect {
+ id: Rect3
+ y: 20; width: 10; height: 10
+ anchors.left: MasterRect.horizontalCenter
+ }
+ Rect {
+ id: Rect4
+ y: 30; width: 10; height: 10
+ anchors.right: MasterRect.left
+ }
+ Rect {
+ id: Rect5
+ y: 30; width: 10; height: 10
+ anchors.right: MasterRect.right
+ }
+ Rect {
+ id: Rect6
+ y: 30; width: 10; height: 10
+ anchors.right: MasterRect.horizontalCenter
+ }
+ Rect {
+ id: Rect7
+ y: 50; width: 10; height: 10
+ anchors.left: parent.left
+ }
+ Rect {
+ id: Rect8
+ y: 50; width: 10; height: 10
+ anchors.left: parent.right
+ }
+ Rect {
+ id: Rect9
+ y: 50; width: 10; height: 10
+ anchors.left: parent.horizontalCenter
+ }
+ Rect {
+ id: Rect10
+ y: 60; width: 10; height: 10
+ anchors.right: parent.left
+ }
+ Rect {
+ id: Rect11
+ y: 60; width: 10; height: 10
+ anchors.right: parent.right
+ }
+ Rect {
+ id: Rect12
+ y: 60; width: 10; height: 10
+ anchors.right: parent.horizontalCenter
+ }
+ Rect {
+ id: Rect13
+ x: 200; width: 10; height: 10
+ anchors.top: MasterRect.bottom
+ }
+ Rect {
+ id: Rect14
+ width: 10; height: 10; color: "steelblue"
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ Rect {
+ id: Rect15
+ y: 200; height: 10
+ anchors.left: MasterRect.left
+ anchors.right: MasterRect.right
+ }
+ Rect {
+ id: Rect16
+ y: 220; height: 10
+ anchors.left: MasterRect.left
+ anchors.horizontalCenter: MasterRect.right
+ }
+ Rect {
+ id: Rect17
+ y: 240; height: 10
+ anchors.right: MasterRect.right
+ anchors.horizontalCenter: MasterRect.left
+ }
+ Rect {
+ id: Rect18
+ x: 180; width: 10
+ anchors.top: MasterRect.bottom
+ anchors.bottom: Rect12.top
+ }
+ Rect {
+ id: Rect19
+ y: 70; width: 10; height: 10
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ Rect {
+ id: Rect20
+ y: 70; width: 10; height: 10
+ anchors.horizontalCenter: parent.right
+ }
+ Rect {
+ id: Rect21
+ y: 70; width: 10; height: 10
+ anchors.horizontalCenter: parent.left
+ }
+}
diff --git a/tests/auto/declarative/anchors/data/illegal1.qml b/tests/auto/declarative/anchors/data/illegal1.qml
new file mode 100644
index 0000000..635bf95
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/illegal1.qml
@@ -0,0 +1,10 @@
+Rect {
+ id: rect
+ width: 120; height: 200; color: "white"
+ Rect { id: TheRect; width: 100; height: 100 }
+ Rect {
+ anchors.left: TheRect.left
+ anchors.right: TheRect.right
+ anchors.horizontalCenter: TheRect.horizontalCenter
+ }
+}
diff --git a/tests/auto/declarative/anchors/data/illegal2.qml b/tests/auto/declarative/anchors/data/illegal2.qml
new file mode 100644
index 0000000..425d0e4
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/illegal2.qml
@@ -0,0 +1,11 @@
+Rect {
+ id: rect
+ width: 120; height: 200; color: "white"
+ Text { id: Text1; text: "Hello" }
+ Text {
+ id: Text2;
+ anchors.baseline: Text1.baseline;
+ anchors.top: Text1.top;
+ text: "World"
+ }
+}
diff --git a/tests/auto/declarative/anchors/data/illegal3.qml b/tests/auto/declarative/anchors/data/illegal3.qml
new file mode 100644
index 0000000..fa48b78
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/illegal3.qml
@@ -0,0 +1,10 @@
+Rect {
+ id: rect
+ width: 120; height: 200; color: "white"
+ Item {
+ Rect { id: TheRect; width: 100; height: 100 }
+ }
+ Rect {
+ anchors.left: TheRect.left
+ }
+}
diff --git a/tests/auto/declarative/anchors/data/loop1.qml b/tests/auto/declarative/anchors/data/loop1.qml
new file mode 100644
index 0000000..a4de1bf
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/loop1.qml
@@ -0,0 +1,6 @@
+Rect {
+ id: rect
+ width: 120; height: 200; color: "white"
+ Text { id: Text1; anchors.right: Text2.right; text: "Hello" }
+ Text { id: Text2; anchors.right: Text1.right; anchors.rightMargin: 10; text: "World" }
+}
diff --git a/tests/auto/declarative/anchors/data/loop2.qml b/tests/auto/declarative/anchors/data/loop2.qml
new file mode 100644
index 0000000..4b2c74e
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/loop2.qml
@@ -0,0 +1,18 @@
+Rect {
+ id: container;
+ width: 600;
+ height: 600;
+
+ Image {
+ id: Image1
+ source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/3311388091_ac2a257feb.jpg"
+ anchors.right: Image2.left
+ }
+
+ Image {
+ id: Image2
+ source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/oslo_groupphoto.jpg"
+ anchors.left: Image1.right
+ anchors.leftMargin: 20
+ }
+}
diff --git a/tests/auto/declarative/anchors/tst_anchors.cpp b/tests/auto/declarative/anchors/tst_anchors.cpp
new file mode 100644
index 0000000..587b4ab
--- /dev/null
+++ b/tests/auto/declarative/anchors/tst_anchors.cpp
@@ -0,0 +1,166 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qfxview.h>
+#include <QtDeclarative/qfxrect.h>
+
+class tst_anchors : public QObject
+{
+ Q_OBJECT
+public:
+ tst_anchors() {}
+
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id);
+
+private slots:
+ void basicAnchors();
+ void loops();
+ void illegalSets();
+};
+
+/*
+ Find an item with the specified id.
+*/
+template<typename T>
+T *tst_anchors::findItem(QFxItem *parent, const QString &id)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->QSimpleCanvasItem::children().count(); ++i) {
+ QFxItem *item = qobject_cast<QFxItem*>(parent->QSimpleCanvasItem::children().at(i));
+ if (mo.cast(item) && (id.isEmpty() || item->id() == id)) {
+ return static_cast<T*>(item);
+ }
+ item = findItem<T>(item, id);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+void tst_anchors::basicAnchors()
+{
+ QFxView *view = new QFxView;
+ view->setUrl(QUrl("file://" SRCDIR "/data/anchors.qml"));
+
+ view->execute();
+ qApp->processEvents();
+
+ //sibling horizontal
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect1"))->x(), 26.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect2"))->x(), 122.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect3"))->x(), 74.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect4"))->x(), 16.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect5"))->x(), 112.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect6"))->x(), 64.0);
+
+ //parent horizontal
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect7"))->x(), 0.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect8"))->x(), 240.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect9"))->x(), 120.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect10"))->x(), -10.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect11"))->x(), 230.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect12"))->x(), 110.0);
+
+ //vertical
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect13"))->y(), 20.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect14"))->y(), 155.0);
+
+ //stretch
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect15"))->x(), 26.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect15"))->width(), 96.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect16"))->x(), 26.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect16"))->width(), 192.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect17"))->x(), -70.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect17"))->width(), 192.0);
+
+ //vertical stretch
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect18"))->y(), 20.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect18"))->height(), 40.0);
+
+ //more parent horizontal
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect19"))->x(), 115.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect20"))->x(), 235.0);
+ QCOMPARE(findItem<QFxRect>(view->root(), QLatin1String("Rect21"))->x(), -5.0);
+
+ delete view;
+}
+
+// mostly testing that we don't crash
+void tst_anchors::loops()
+{
+ {
+ QFxView *view = new QFxView;
+
+ view->setUrl(QUrl("file://" SRCDIR "/data/loop1.qml"));
+
+ //### ignoreMessage doesn't seem to work
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Anchor loop detected on horizontal anchor.");
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Anchor loop detected on horizontal anchor.");
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+
+ {
+ QFxView *view = new QFxView;
+
+ view->setUrl(QUrl("file://" SRCDIR "/data/loop2.qml"));
+
+ //### ignoreMessage doesn't seem to work here
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxImage (unknown location): Anchor loop detected on horizontal anchor.");
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxImage (unknown location): Anchor loop detected on horizontal anchor.");
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+}
+
+void tst_anchors::illegalSets()
+{
+ {
+ QFxView *view = new QFxView;
+
+ view->setUrl(QUrl("file://" SRCDIR "/data/illegal1.qml"));
+
+ //### ignoreMessage doesn't seem to work
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxRect (unknown location): Can't specify left, right, and hcenter anchors.");
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+
+ {
+ QFxView *view = new QFxView;
+
+ view->setUrl(QUrl("file://" SRCDIR "/data/illegal2.qml"));
+
+ //### ignoreMessage doesn't seem to work here
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors.");
+ view->execute();
+ //qApp->processEvents();
+
+ delete view;
+ }
+
+ {
+ QFxView *view = new QFxView;
+
+ view->setUrl(QUrl("file://" SRCDIR "/data/illegal3.qml"));
+
+ //### ignoreMessage doesn't seem to work here
+ //QTest::ignoreMessage(QtWarningMsg, "Can't anchor to an item that isn't a parent or sibling.");
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+}
+
+QTEST_MAIN(tst_anchors)
+
+#include "tst_anchors.moc"
diff --git a/tests/auto/declarative/datetimeformatter/datetimeformatter.pro b/tests/auto/declarative/datetimeformatter/datetimeformatter.pro
new file mode 100644
index 0000000..e3d6cd0
--- /dev/null
+++ b/tests/auto/declarative/datetimeformatter/datetimeformatter.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_datetimeformatter.cpp
diff --git a/tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp b/tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp
new file mode 100644
index 0000000..67cff02
--- /dev/null
+++ b/tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp
@@ -0,0 +1,83 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmldatetimeformatter.h>
+
+class tst_datetimeformatter : public QObject
+{
+ Q_OBJECT
+public:
+ tst_datetimeformatter() {}
+
+private slots:
+ void date();
+ void time();
+ void dateTime();
+};
+
+void tst_datetimeformatter::date()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, "DateTimeFormatter { date: \"2008-12-24\" }");
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QDate date(2008,12,24);
+ QCOMPARE(formatter->dateText(),date.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->dateText(),date.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setDateFormat("ddd MMMM d yy");
+ QCOMPARE(formatter->dateText(),date.toString("ddd MMMM d yy"));
+
+ QVERIFY(formatter->timeText().isEmpty());
+ QVERIFY(formatter->dateTimeText().isEmpty());
+}
+
+void tst_datetimeformatter::time()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, "DateTimeFormatter { time: \"14:15:38.200\" }");
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QTime time(14,15,38,200);
+
+ QCOMPARE(formatter->time(),time);
+
+ QCOMPARE(formatter->timeText(),time.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->timeText(),time.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setTimeFormat("H:m:s a");
+ QCOMPARE(formatter->timeText(),time.toString("H:m:s a"));
+
+ formatter->setTimeFormat("hh:mm:ss.zzz");
+ QCOMPARE(formatter->timeText(),time.toString("hh:mm:ss.zzz"));
+
+ QVERIFY(formatter->dateText().isEmpty());
+ QVERIFY(formatter->dateTimeText().isEmpty());
+}
+
+void tst_datetimeformatter::dateTime()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, "DateTimeFormatter { dateTime: \"1978-03-04T09:13:54\" }");
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QDateTime dateTime(QDate(1978,03,04),QTime(9,13,54));
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setDateTimeFormat("M/d/yy H:m:s a");
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString("M/d/yy H:m:s a"));
+}
+
+QTEST_MAIN(tst_datetimeformatter)
+
+#include "tst_datetimeformatter.moc"
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
new file mode 100644
index 0000000..14d8c24
--- /dev/null
+++ b/tests/auto/declarative/declarative.pro
@@ -0,0 +1,23 @@
+TEMPLATE = subdirs
+SUBDIRS += datetimeformatter \
+ numberformatter \
+ qbindablemap \
+ layouts \
+ listview \
+ pathview \
+ qfxtext \
+ qfxtextedit \
+ simplecanvasitem \
+ repeater \
+ qmlparser \
+ qmlbindengine \
+ qmlmetaproperty \
+ qmllist \
+ qmllistaccessor \
+ visual\
+ qmlengine
+
+# Tests which should run in Pulse
+PULSE_TESTS = $$SUBDIRS
+PULSE_TESTS -= visual # All except 'visual' tests, allegedly too flaky
+
diff --git a/tests/auto/declarative/layouts/data/grid-margin.qml b/tests/auto/declarative/layouts/data/grid-margin.qml
new file mode 100644
index 0000000..bae47f9
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid-margin.qml
@@ -0,0 +1,38 @@
+Item {
+ width: 640
+ height: 480
+ GridLayout {
+ columns: 3
+ margin: 8
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rect {
+ id: three
+ color: "blue"
+ width: 50
+ height: 20
+ }
+ Rect {
+ id: four
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: five
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/grid-spacing-margin.qml b/tests/auto/declarative/layouts/data/grid-spacing-margin.qml
new file mode 100644
index 0000000..100d8c5
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid-spacing-margin.qml
@@ -0,0 +1,39 @@
+Item {
+ width: 640
+ height: 480
+ GridLayout {
+ columns: 3
+ spacing: 4
+ margin: 8
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rect {
+ id: three
+ color: "blue"
+ width: 50
+ height: 20
+ }
+ Rect {
+ id: four
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: five
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/grid-spacing.qml b/tests/auto/declarative/layouts/data/grid-spacing.qml
new file mode 100644
index 0000000..494127b
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid-spacing.qml
@@ -0,0 +1,38 @@
+Item {
+ width: 640
+ height: 480
+ GridLayout {
+ columns: 3
+ spacing: 4
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rect {
+ id: three
+ color: "blue"
+ width: 50
+ height: 20
+ }
+ Rect {
+ id: four
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: five
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/grid.qml b/tests/auto/declarative/layouts/data/grid.qml
new file mode 100644
index 0000000..598915f
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid.qml
@@ -0,0 +1,37 @@
+Item {
+ width: 640
+ height: 480
+ GridLayout {
+ columns: 3
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rect {
+ id: three
+ color: "blue"
+ width: 50
+ height: 20
+ }
+ Rect {
+ id: four
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: five
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/horizontal-margin.qml b/tests/auto/declarative/layouts/data/horizontal-margin.qml
new file mode 100644
index 0000000..8bf2329
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal-margin.qml
@@ -0,0 +1,25 @@
+Item {
+ width: 640
+ height: 480
+ HorizontalLayout {
+ margin: 10
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/horizontal-spacing-margin.qml b/tests/auto/declarative/layouts/data/horizontal-spacing-margin.qml
new file mode 100644
index 0000000..79652f6
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal-spacing-margin.qml
@@ -0,0 +1,26 @@
+Item {
+ width: 640
+ height: 480
+ HorizontalLayout {
+ spacing: 5
+ margin: 10
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/horizontal-spacing.qml b/tests/auto/declarative/layouts/data/horizontal-spacing.qml
new file mode 100644
index 0000000..5130e4a
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal-spacing.qml
@@ -0,0 +1,25 @@
+Item {
+ width: 640
+ height: 480
+ HorizontalLayout {
+ spacing: 10
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/horizontal.qml b/tests/auto/declarative/layouts/data/horizontal.qml
new file mode 100644
index 0000000..7ad6b55
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal.qml
@@ -0,0 +1,24 @@
+Item {
+ width: 640
+ height: 480
+ HorizontalLayout {
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/vertical-margin.qml b/tests/auto/declarative/layouts/data/vertical-margin.qml
new file mode 100644
index 0000000..ad34906
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical-margin.qml
@@ -0,0 +1,25 @@
+Item {
+ width: 640
+ height: 480
+ VerticalLayout {
+ margin: 10
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/vertical-spacing-margin.qml b/tests/auto/declarative/layouts/data/vertical-spacing-margin.qml
new file mode 100644
index 0000000..5de50b3
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical-spacing-margin.qml
@@ -0,0 +1,26 @@
+Item {
+ width: 640
+ height: 480
+ VerticalLayout {
+ spacing: 5
+ margin: 10
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/vertical-spacing.qml b/tests/auto/declarative/layouts/data/vertical-spacing.qml
new file mode 100644
index 0000000..c364e3f
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical-spacing.qml
@@ -0,0 +1,25 @@
+Item {
+ width: 640
+ height: 480
+ VerticalLayout {
+ spacing: 10
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/data/vertical.qml b/tests/auto/declarative/layouts/data/vertical.qml
new file mode 100644
index 0000000..50931cd
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical.qml
@@ -0,0 +1,24 @@
+Item {
+ width: 640
+ height: 480
+ VerticalLayout {
+ Rect {
+ id: one
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rect {
+ id: two
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rect {
+ id: three
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/layouts.pro b/tests/auto/declarative/layouts/layouts.pro
new file mode 100644
index 0000000..f7e7622
--- /dev/null
+++ b/tests/auto/declarative/layouts/layouts.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_layouts.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/layouts/tst_layouts.cpp b/tests/auto/declarative/layouts/tst_layouts.cpp
new file mode 100644
index 0000000..732551c
--- /dev/null
+++ b/tests/auto/declarative/layouts/tst_layouts.cpp
@@ -0,0 +1,392 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxrect.h>
+#include <qmlexpression.h>
+
+class tst_QFxLayouts : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxLayouts();
+
+private slots:
+ void test_horizontal();
+ void test_horizontal_spacing();
+ void test_horizontal_margin();
+ void test_horizontal_spacing_margin();
+ void test_vertical();
+ void test_vertical_spacing();
+ void test_vertical_margin();
+ void test_vertical_spacing_margin();
+ void test_grid();
+ void test_grid_spacing();
+ void test_grid_margin();
+ void test_grid_spacing_margin();
+
+private:
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id, int index=0);
+};
+
+tst_QFxLayouts::tst_QFxLayouts()
+{
+}
+
+void tst_QFxLayouts::test_horizontal()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+}
+
+void tst_QFxLayouts::test_horizontal_spacing()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 60.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 90.0);
+ QCOMPARE(three->y(), 0.0);
+}
+
+void tst_QFxLayouts::test_horizontal_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal-margin.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 60.0);
+ QCOMPARE(two->y(), 10.0);
+ QCOMPARE(three->x(), 80.0);
+ QCOMPARE(three->y(), 10.0);
+}
+
+void tst_QFxLayouts::test_horizontal_spacing_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal-spacing-margin.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 65.0);
+ QCOMPARE(two->y(), 10.0);
+ QCOMPARE(three->x(), 90.0);
+ QCOMPARE(three->y(), 10.0);
+}
+
+void tst_QFxLayouts::test_vertical()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 60.0);
+}
+
+void tst_QFxLayouts::test_vertical_spacing()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical-spacing.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 60.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 80.0);
+}
+
+void tst_QFxLayouts::test_vertical_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical-margin.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 10.0);
+ QCOMPARE(two->y(), 60.0);
+ QCOMPARE(three->x(), 10.0);
+ QCOMPARE(three->y(), 70.0);
+}
+
+void tst_QFxLayouts::test_vertical_spacing_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical-spacing-margin.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 10.0);
+ QCOMPARE(two->y(), 65.0);
+ QCOMPARE(three->x(), 10.0);
+ QCOMPARE(three->y(), 80.0);
+}
+
+void tst_QFxLayouts::test_grid()
+{
+ QFxView *canvas = createView("data/grid.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
+}
+
+void tst_QFxLayouts::test_grid_spacing()
+{
+ QFxView *canvas = createView("data/grid-spacing.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 54.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 78.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 54.0);
+ QCOMPARE(five->x(), 54.0);
+ QCOMPARE(five->y(), 54.0);
+}
+
+void tst_QFxLayouts::test_grid_margin()
+{
+ QFxView *canvas = createView("data/grid-margin.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 8.0);
+ QCOMPARE(one->y(), 8.0);
+ QCOMPARE(two->x(), 58.0);
+ QCOMPARE(two->y(), 8.0);
+ QCOMPARE(three->x(), 78.0);
+ QCOMPARE(three->y(), 8.0);
+ QCOMPARE(four->x(), 8.0);
+ QCOMPARE(four->y(), 58.0);
+ QCOMPARE(five->x(), 58.0);
+ QCOMPARE(five->y(), 58.0);
+}
+
+
+void tst_QFxLayouts::test_grid_spacing_margin()
+{
+ QFxView *canvas = createView("data/grid-spacing-margin.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 8.0);
+ QCOMPARE(one->y(), 8.0);
+ QCOMPARE(two->x(), 62.0);
+ QCOMPARE(two->y(), 8.0);
+ QCOMPARE(three->x(), 86.0);
+ QCOMPARE(three->y(), 8.0);
+ QCOMPARE(four->x(), 8.0);
+ QCOMPARE(four->y(), 62.0);
+ QCOMPARE(five->x(), 62.0);
+ QCOMPARE(five->y(), 62.0);
+}
+
+QFxView *tst_QFxLayouts::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setQml(xml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified id. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QFxLayouts::findItem(QFxItem *parent, const QString &id, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = parent->children()->at(i);
+ if (mo.cast(item) && (id.isEmpty() || item->id() == id)) {
+ if (index != -1) {
+ QmlExpression e(qmlContext(item), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, id, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxLayouts)
+
+#include "tst_layouts.moc"
diff --git a/tests/auto/declarative/listview/data/listview.qml b/tests/auto/declarative/listview/data/listview.qml
new file mode 100644
index 0000000..891f9a8
--- /dev/null
+++ b/tests/auto/declarative/listview/data/listview.qml
@@ -0,0 +1,39 @@
+Rect {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: Delegate
+ Item {
+ id: wrapper
+ height: 20
+ width: 240
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ text: name
+ }
+ Text {
+ x: 120
+ id: textNumber
+ text: number
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ }
+ }
+ ]
+ ListView {
+ id: list
+ width: 240
+ height: 320
+ model: testModel
+ delegate: Delegate
+ }
+}
diff --git a/tests/auto/declarative/listview/listview.pro b/tests/auto/declarative/listview/listview.pro
new file mode 100644
index 0000000..bf68268
--- /dev/null
+++ b/tests/auto/declarative/listview/listview.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_listview.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/listview/tst_listview.cpp b/tests/auto/declarative/listview/tst_listview.cpp
new file mode 100644
index 0000000..8cf0a85
--- /dev/null
+++ b/tests/auto/declarative/listview/tst_listview.cpp
@@ -0,0 +1,486 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxlistview.h>
+#include <qfxtext.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+
+class tst_QFxListView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxListView();
+
+private slots:
+ // Test both QListModelInterface and QAbstractItemModel model types
+ void qListModelInterface_items();
+ void qAbstractItemModel_items();
+
+ void qListModelInterface_changed();
+ void qAbstractItemModel_changed();
+
+ void qListModelInterface_inserted();
+ void qAbstractItemModel_inserted();
+
+ void qListModelInterface_removed();
+ void qAbstractItemModel_removed();
+
+private:
+ template <class T> void items();
+ template <class T> void changed();
+ template <class T> void inserted();
+ template <class T> void removed();
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id, int index=0);
+};
+
+class TestModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
+ ~TestModel() {}
+
+ enum Roles { Name, Number };
+
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ int count() const { return list.count(); }
+
+ QList<int> roles() const { return QList<int>() << Name << Number; }
+ QString toString(int role) const {
+ switch(role) {
+ case Name:
+ return "name";
+ case Number:
+ return "number";
+ default:
+ return "";
+ }
+ }
+
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const {
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case Name:
+ info = list.at(index).first;
+ break;
+ case Number:
+ info = list.at(index).second;
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+ }
+
+ void addItem(const QString &name, const QString &number) {
+ list.append(QPair<QString,QString>(name, number));
+ emit itemsInserted(list.count()-1, 1);
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit itemsInserted(index, 1);
+ }
+
+ void removeItem(int index) {
+ list.removeAt(index);
+ emit itemsRemoved(index, 1);
+ }
+
+ void modifyItem(int index, const QString &name, const QString &number) {
+ list[index] = QPair<QString,QString>(name, number);
+ emit itemsChanged(index, 1, roles());
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+class TestModel2 : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel2(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QFxListView::tst_QFxListView()
+{
+}
+
+template <class T>
+void tst_QFxListView::items()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxFlickable *listview = findItem<QFxFlickable>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ QCOMPARE(viewport->children()->count(), model.count()); // assumes all are visible
+
+ for (int i = 0; i < model.count(); ++i) {
+ QFxText *name = findItem<QFxText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QFxListView::changed()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxFlickable *listview = findItem<QFxFlickable>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.modifyItem(1, "Will", "9876");
+ QFxText *name = findItem<QFxText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QFxListView::inserted()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxListView *listview = findItem<QFxListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.insertItem(1, "Will", "9876");
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ QCOMPARE(viewport->children()->count(), model.count()); // assumes all are visible
+
+ QFxText *name = findItem<QFxText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QVERIFY(item->y() == i*20);
+ }
+
+ model.insertItem(0, "Foo", "1111"); // zero index, and current item
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ QCOMPARE(viewport->children()->count(), model.count()); // assumes all are visible
+
+ name = findItem<QFxText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QFxText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ QCOMPARE(listview->currentIndex(), 1);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QVERIFY(item->y() == i*20);
+ }
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QFxListView::removed()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxListView *listview = findItem<QFxListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.removeItem(1);
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ QFxText *name = findItem<QFxText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QVERIFY(item->y() == i*20);
+ }
+
+ // Remove first item (which is the current item);
+ model.removeItem(0); // post: top item starts at 20
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ name = findItem<QFxText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QFxText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),i*20.0 + 20.0);
+ }
+
+ // Remove items not visible
+ model.removeItem(18);
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),i*20.0+20.0);
+ }
+
+ // Remove items before visible
+ listview->setYPosition(80);
+ listview->setCurrentIndex(10);
+
+ model.removeItem(1); // post: top item will be at 40
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ // Confirm items positioned correctly
+ for (int i = 2; i < 18; ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),40+i*20.0);
+ }
+
+ listview->setYPosition(40); // That's the top now
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),40+i*20.0);
+ }
+
+ delete canvas;
+}
+
+void tst_QFxListView::qListModelInterface_items()
+{
+ items<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_items()
+{
+ items<TestModel2>();
+}
+
+void tst_QFxListView::qListModelInterface_changed()
+{
+ changed<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_changed()
+{
+ changed<TestModel2>();
+}
+
+void tst_QFxListView::qListModelInterface_inserted()
+{
+ inserted<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_inserted()
+{
+ inserted<TestModel2>();
+}
+
+void tst_QFxListView::qListModelInterface_removed()
+{
+ removed<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_removed()
+{
+ removed<TestModel2>();
+}
+
+QFxView *tst_QFxListView::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified id. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QFxListView::findItem(QFxItem *parent, const QString &id, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ qDebug() << parent->children()->count() << "children";
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = parent->children()->at(i);
+ qDebug() << "try" << item;
+ if (mo.cast(item) && (id.isEmpty() || item->id() == id)) {
+ if (index != -1) {
+ QmlExpression e(qmlContext(item), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, id, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxListView)
+
+#include "tst_listview.moc"
diff --git a/tests/auto/declarative/numberformatter/numberformatter.pro b/tests/auto/declarative/numberformatter/numberformatter.pro
new file mode 100644
index 0000000..ba391ed
--- /dev/null
+++ b/tests/auto/declarative/numberformatter/numberformatter.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_numberformatter.cpp
diff --git a/tests/auto/declarative/numberformatter/tst_numberformatter.cpp b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp
new file mode 100644
index 0000000..e70d651
--- /dev/null
+++ b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp
@@ -0,0 +1,216 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qnumberformat.h>
+#include <QtDeclarative/qmlnumberformatter.h>
+
+class tst_numberformat : public QObject
+{
+ Q_OBJECT
+public:
+ tst_numberformat();
+
+ void init() {}
+ void initTestCase() {}
+
+ void cleanup() {}
+ void cleanupTestCase() {}
+
+private slots:
+ void number_data();
+ void number();
+
+ void text_data();
+ void text();
+
+private:
+ QStringList strings;
+ QList<float> numbers;
+ QStringList formats;
+ QStringList texts;
+};
+
+tst_numberformat::tst_numberformat()
+{
+ strings << "100.0"
+ << "12345"
+ << "1234567"
+ << "0.123"
+ << "0.9999"
+ << "0.989"
+ << "1"
+ << "1.0"
+ << "1.01";
+
+ numbers << 100
+ << 12345
+ << 1234567
+ << 0.123
+ << 0.9999
+ << 0.989
+ << 1
+ << 1.0
+ << 1.01;
+
+ formats << ""
+ << "0000"
+ << "0000.00"
+ << "##"
+ << "##.##"
+ << "#0.00#"
+ << "##,##0.##"
+ << "(000) 000 - 000"
+ << "00000,000.0000";
+
+ //US locale only.
+ texts << "100.000000"
+ << "12345.000000"
+ << "1234567.000000"
+ << "0.123000"
+ << "0.999900"
+ << "0.989000"
+ << "1.000000"
+ << "1.000000"
+ << "1.010000" //end ""
+ << "0100"
+ << "12345"
+ << "1234567"
+ << "0000"
+ << "0001"
+ << "0001"
+ << "0001"
+ << "0001"
+ << "0001" // end "0000"
+ << "0100.00"
+ << "12345.00"
+ << "1234567.00"
+ << "0000.12"
+ << "0001.00"
+ << "0000.99"
+ << "0001.00"
+ << "0001.00"
+ << "0001.01" // end "0000.00"
+ << "100"
+ << "12345"
+ << "1234567"
+ << "0"
+ << "1"
+ << "1"
+ << "1"
+ << "1"
+ << "1" // end "##"
+ << "100"//start "##.##"
+ << "12345"
+ << "1234567"
+ << "0.12"
+ << "1"
+ << "0.99"
+ << "1"
+ << "1"
+ << "1.01" // end "##.##" -- ### EXPECT FAIL ### QNumberFormat::formatDecimal() bug
+ << "100.00" //start "#0.00#"
+ << "12345.00"
+ << "1234567.00"
+ << "0.123"
+ << "1.00"
+ << "0.989"
+ << "1.00"
+ << "1.00"
+ << "1.01" //end "#0.00#"
+ << "100" //start "##,##0.##"
+ << "12,345"
+ << "1,234,567"
+ << "0.12"
+ << "1"
+ << "0.99"
+ << "1"
+ << "1"
+ << "1.01" //end "##,##0.##" -- ### EXPECT FAIL ### QNumberFormat::formatDecimal() bug
+ << "(000) 000 - 100" //start "(000) 000 - 000"
+ << "(000) 012 - 345"
+ << "(001) 234 - 567"
+ << "(000) 000 - 000"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001" // end "(000) 000 - 000"
+ << "00,000,100.0000" // start "00000,000.0000"
+ << "00,012,345.0000"
+ << "01,234,567.0000"
+ << "00,000,000.1230"
+ << "00,000,000.9999"
+ << "00,000,000.9890"
+ << "00,000,001.0000"
+ << "00,000,001.0000"
+ << "00,000,001.0100"; // end
+
+ qDebug() << "strings.size()" << strings.size()
+ << "\nformats.size()" << formats.size()
+ << "texts.size()" << texts.size();
+}
+
+void tst_numberformat::number_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<float>("number");
+
+ for (int i = 0; i < strings.size(); i++)
+ QTest::newRow(QString::number(i).toAscii()) << strings.at(i) << numbers.at(i);
+}
+
+void tst_numberformat::number()
+{
+ // ### tests the conversion from string to float
+ QFETCH(QString, string);
+ QFETCH(float, number);
+
+ QString componentStr = QString("NumberFormatter { number: \"") + string + QString("\" }");
+
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, componentStr.toAscii());
+ QmlNumberFormatter *formatter = qobject_cast<QmlNumberFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+ QCOMPARE((float)formatter->number(), number);
+ //qDebug() << formatter->format() << formatter->text();
+ QVERIFY(formatter->format().isEmpty());
+ QVERIFY(formatter->text() == QString("%1").arg(number, -1, 'f', -1));
+}
+
+void tst_numberformat::text_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<QString>("text");
+
+ for (int j=0; j < formats.size(); j++)
+ {
+ for (int i=0; i < strings.size(); i++)
+ {
+ QTest::newRow(QString("%1, %2").arg(strings.at(i)).arg(formats.at(j)).toAscii())
+ << strings.at(i) << formats.at(j) << texts.at(j*formats.size()+i);
+ }
+ }
+
+}
+
+void tst_numberformat::text()
+{
+ QFETCH(QString, string);
+ QFETCH(QString, format);
+ QFETCH(QString, text);
+
+ QString componentStr = QString("NumberFormatter { number: \"") + string + QString("\"; format: \"") + format + QString("\" }");
+
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, componentStr.toAscii());
+ QmlNumberFormatter *formatter = qobject_cast<QmlNumberFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QCOMPARE(formatter->format(), format);
+ QCOMPARE(formatter->text(), text);
+}
+
+QTEST_MAIN(tst_numberformat)
+
+#include "tst_numberformatter.moc"
diff --git a/tests/auto/declarative/pathview/data/pathview.qml b/tests/auto/declarative/pathview/data/pathview.qml
new file mode 100644
index 0000000..0fec1e9
--- /dev/null
+++ b/tests/auto/declarative/pathview/data/pathview.qml
@@ -0,0 +1,60 @@
+Rect {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: Delegate
+ Rect {
+ id: wrapper
+ height: 20
+ width: 60
+ color: "white"
+ pen.color: "black"
+ Text {
+ text: index
+ }
+ Text {
+ x: 20
+ id: textName
+ text: name
+ }
+ Text {
+ x: 40
+ id: textNumber
+ text: number
+ }
+ }
+ }
+ ]
+ PathView {
+ id: view
+ width: 240
+ height: 320
+ model: testModel
+ delegate: Delegate
+ snapPos: 0.01
+ path: Path {
+ startY: 120
+ startX: 160
+ PathQuad {
+ y: 120
+ x: 80
+ controlY: 330
+ controlX: 100
+ }
+ PathLine {
+ y: 160
+ x: 20
+ }
+ PathCubic {
+ y: 120
+ x: 160
+ control1Y: 0
+ control1X: 100
+ control2Y: 000
+ control2X: 200
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/pathview/pathview.pro b/tests/auto/declarative/pathview/pathview.pro
new file mode 100644
index 0000000..28bbe49
--- /dev/null
+++ b/tests/auto/declarative/pathview/pathview.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_pathview.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/pathview/tst_pathview.cpp b/tests/auto/declarative/pathview/tst_pathview.cpp
new file mode 100644
index 0000000..92890ba
--- /dev/null
+++ b/tests/auto/declarative/pathview/tst_pathview.cpp
@@ -0,0 +1,259 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxpathview.h>
+#include <qfxtext.h>
+#include <qfxrect.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+
+class tst_QFxPathView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxPathView();
+
+private slots:
+ void items();
+ void pathMoved();
+ void limitedItems();
+
+private:
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id, int index=0);
+};
+
+class TestModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
+ ~TestModel() {}
+
+ enum Roles { Name, Number };
+
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ int count() const { return list.count(); }
+
+ QList<int> roles() const { return QList<int>() << Name << Number; }
+ QString toString(int role) const {
+ switch(role) {
+ case Name:
+ return "name";
+ case Number:
+ return "number";
+ default:
+ return "";
+ }
+ }
+
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const {
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case Name:
+ info = list.at(index).first;
+ break;
+ case Number:
+ info = list.at(index).second;
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+ }
+
+ void addItem(const QString &name, const QString &number) {
+ list.append(QPair<QString,QString>(name, number));
+ emit itemsInserted(list.count()-1, 1);
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit itemsInserted(index, 1);
+ }
+
+ void removeItem(int index) {
+ list.removeAt(index);
+ emit itemsRemoved(index, 1);
+ }
+
+ void modifyItem(int index, const QString &name, const QString &number) {
+ list[index] = QPair<QString,QString>(name, number);
+ emit itemsChanged(index, 1, roles());
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QFxPathView::tst_QFxPathView()
+{
+}
+
+void tst_QFxPathView::items()
+{
+ QFxView *canvas = createView(SRCDIR "/data/pathview.xml");
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxPathView *pathview = findItem<QFxPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ QCOMPARE(pathview->children()->count(), model.count()); // assumes all are visible
+
+ for (int i = 0; i < model.count(); ++i) {
+ QFxText *name = findItem<QFxText>(pathview, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QFxText *number = findItem<QFxText>(pathview, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QFxPathView::pathMoved()
+{
+ QFxView *canvas = createView(SRCDIR "/data/pathview.xml");
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxPathView *pathview = findItem<QFxPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ QFxRect *firstItem = findItem<QFxRect>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QFxPath *path = qobject_cast<QFxPath*>(pathview->path());
+ QVERIFY(path);
+ QPointF start = path->pointAt(0.0);
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(firstItem->width()/2);
+ offset.setY(firstItem->height()/2);
+ QCOMPARE(firstItem->pos() + offset, start);
+ pathview->setOffset(10);
+ QTest::qWait(1000);//Moving is animated?
+
+ for(int i=0; i<model.count(); i++){
+ QFxRect *curItem = findItem<QFxRect>(pathview, "wrapper", i);
+ QCOMPARE(curItem->pos() + offset, path->pointAt(0.1 + i*0.25));
+ }
+
+ pathview->setOffset(100);
+ QTest::qWait(1000);//Moving is animated?
+ QCOMPARE(firstItem->pos() + offset, start);
+
+ delete canvas;
+}
+
+void tst_QFxPathView::limitedItems()
+{
+ QFxView *canvas = createView(SRCDIR "/data/pathview.xml");
+
+ TestModel model;
+ for(int i=0; i<100; i++)
+ model.addItem("Bob", QString::number(i));
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxPathView *pathview = findItem<QFxPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ pathview->setPathItemCount(10);
+ QCOMPARE(pathview->pathItemCount(), 10);
+
+ QFxRect *testItem = findItem<QFxRect>(pathview, "wrapper", 0);
+ QVERIFY(testItem != 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 9);
+ QVERIFY(testItem != 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 10);
+ QVERIFY(testItem == 0);
+
+ pathview->setCurrentIndex(50);
+ QTest::qWait(5100);//Moving is animated and it's travelling far - should be reconsidered.
+ testItem = findItem<QFxRect>(pathview, "wrapper", 0);
+ QVERIFY(testItem == 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 1);
+ QVERIFY(testItem == 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 9);
+ QVERIFY(testItem == 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 50);
+ QVERIFY(testItem != 0);
+}
+
+QFxView *tst_QFxPathView::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setQml(xml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified id. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QFxPathView::findItem(QFxItem *parent, const QString &id, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = parent->children()->at(i);
+ if (mo.cast(item) && (id.isEmpty() || item->id() == id)) {
+ if (index != -1) {
+ QmlExpression e(qmlContext(item), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, id, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxPathView)
+
+#include "tst_pathview.moc"
diff --git a/tests/auto/declarative/qbindablemap/qbindablemap.pro b/tests/auto/declarative/qbindablemap/qbindablemap.pro
new file mode 100644
index 0000000..b042405
--- /dev/null
+++ b/tests/auto/declarative/qbindablemap/qbindablemap.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qbindablemap.cpp
diff --git a/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp b/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp
new file mode 100644
index 0000000..a8046e6
--- /dev/null
+++ b/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp
@@ -0,0 +1,72 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qbindablemap.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QSignalSpy>
+
+class tst_QBindableMap : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QBindableMap() {}
+
+private slots:
+ void insert();
+ void clear();
+ void changed();
+};
+
+void tst_QBindableMap::insert()
+{
+ QBindableMap map;
+ map.setValue(QLatin1String("key1"),100);
+ map.setValue(QLatin1String("key2"),200);
+ QVERIFY(map.keys().count() == 2);
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
+ QCOMPARE(map.value(QLatin1String("key2")), QVariant(200));
+
+ map.setValue(QLatin1String("key1"),"Hello World");
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World"));
+}
+
+void tst_QBindableMap::clear()
+{
+ QBindableMap map;
+ map.setValue(QLatin1String("key1"),100);
+ QVERIFY(map.keys().count() == 1);
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
+
+ map.clearValue(QLatin1String("key1"));
+ QVERIFY(map.keys().count() == 1);
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant());
+}
+
+void tst_QBindableMap::changed()
+{
+ QBindableMap map;
+ QSignalSpy spy(&map, SIGNAL(changed(const QString&)));
+ map.setValue(QLatin1String("key1"),100);
+ map.setValue(QLatin1String("key2"),200);
+ QCOMPARE(spy.count(), 0);
+
+ map.clearValue(QLatin1String("key1"));
+ QCOMPARE(spy.count(), 0);
+
+ //make changes in QML
+ QmlEngine engine;
+ QmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty(QLatin1String("data"), &map);
+ QmlComponent component(&engine, "Script { script: \"data.key1 = 'Hello World';\" }");
+ component.create();
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toString(),QLatin1String("key1"));
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World"));
+}
+
+QTEST_MAIN(tst_QBindableMap)
+
+#include "tst_qbindablemap.moc"
diff --git a/tests/auto/declarative/qfxtext/qfxtext.pro b/tests/auto/declarative/qfxtext/qfxtext.pro
new file mode 100644
index 0000000..f705334
--- /dev/null
+++ b/tests/auto/declarative/qfxtext/qfxtext.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+SOURCES += tst_qfxtext.cpp
diff --git a/tests/auto/declarative/qfxtext/tst_qfxtext.cpp b/tests/auto/declarative/qfxtext/tst_qfxtext.cpp
new file mode 100644
index 0000000..0eb9f97
--- /dev/null
+++ b/tests/auto/declarative/qfxtext/tst_qfxtext.cpp
@@ -0,0 +1,413 @@
+#include <qtest.h>
+#include <QTextDocument>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qfxtext.h>
+#include <QFontMetrics>
+
+class tst_qfxtext : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qfxtext();
+
+private slots:
+ void text();
+ void width();
+ void wrap();
+ void elide();
+
+ // ### these tests may be trivial
+ void hAlign();
+ void vAlign();
+ void font();
+ void style();
+ void color();
+
+private:
+ QStringList standard;
+ QStringList richText;
+
+ QStringList hAlignmentStrings;
+ QStringList vAlignmentStrings;
+
+ QList<Qt::Alignment> vAlignments;
+ QList<Qt::Alignment> hAlignments;
+
+ QStringList styleStrings;
+ QList<QFxText::TextStyle> styles;
+
+ QStringList colorStrings;
+
+ QmlEngine engine;
+};
+
+tst_qfxtext::tst_qfxtext()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog";
+
+ richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ hAlignmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ vAlignmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ hAlignments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ vAlignments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ styleStrings << "Normal"
+ << "Outline"
+ << "Raised"
+ << "Sunken";
+
+ styles << QFxText::Normal
+ << QFxText::Outline
+ << QFxText::Raised
+ << QFxText::Sunken;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+void tst_qfxtext::text()
+{
+ {
+ QmlComponent textComponent(&engine, "Text { text: \"\" }");
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), QString(""));
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "Text { text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), standard.at(i));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "Text { text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QString expected = richText.at(i);
+ QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
+ }
+}
+
+void tst_qfxtext::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QmlComponent textComponent(&engine, "Text { text: \"\" }");
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 0.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ QFontMetrics fm(f);
+ int metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+
+ QString componentStr = "Text { text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), qreal(metricWidth));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QTextDocument document;
+ document.setHtml(richText.at(i));
+ document.setDocumentMargin(0);
+
+ int documentWidth = document.idealWidth();
+
+ QString componentStr = "Text { text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), qreal(documentWidth));
+ }
+}
+
+void tst_qfxtext::wrap()
+{
+ // XXX Poor coverage - should at least be testing an expected height.
+
+ // for specified width and wrap set true
+ {
+ QmlComponent textComponent(&engine, "Text { text: \"\"; wrap: true; width: 300 }");
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "Text { wrap: true; width: 300; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "Text { wrap: true; width: 300; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+}
+
+void tst_qfxtext::elide()
+{
+ for (Qt::TextElideMode m = Qt::ElideLeft; m<=Qt::ElideNone; m=Qt::TextElideMode(int(m)+1)) {
+ const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
+ QString elide = "elide: \""+QString(elidename[int(m)])+"\";";
+
+ // XXX Poor coverage.
+
+ {
+ QmlComponent textComponent(&engine, ("Text { text: \"\"; "+elide+" width: 300 }").toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "Text { "+elide+" width: 300; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ // richtext - does nothing
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "Text { "+elide+" width: 300; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+ }
+}
+
+//the alignment tests may be trivial o.oa
+void tst_qfxtext::hAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "Text { hAlign: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "Text { hAlign: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtext::vAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "Text { vAlign: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "Text { vAlign: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtext::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "Text { font.size: 40; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->size(), qreal(40));
+ QCOMPARE(textObject->font()->bold(), false);
+ QCOMPARE(textObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "Text { font.bold: true; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->bold(), true);
+ QCOMPARE(textObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "Text { font.italic: true; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->italic(), true);
+ QCOMPARE(textObject->font()->bold(), false);
+ }
+
+ {
+ QString componentStr = "Text { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->family(), QString("Helvetica"));
+ QCOMPARE(textObject->font()->bold(), false);
+ QCOMPARE(textObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "Text { font.family: \"\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->family(), QString(""));
+ }
+}
+
+void tst_qfxtext::style()
+{
+ //test style
+ for (int i = 0; i < styles.size(); i++)
+ {
+ QString componentStr = "Text { style: \"" + styleStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->style(), (int)styles.at(i));
+ QCOMPARE(textObject->styleColor(), QColor());
+ }
+}
+
+void tst_qfxtext::color()
+{
+ //test style
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "Text { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor());
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "Text { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
+ // default color to black?
+ QCOMPARE(textObject->color(), QColor("black"));
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ for (int j = 0; j < colorStrings.size(); j++)
+ {
+ QString componentStr = "Text { color: \"" + colorStrings.at(i) + "\"; styleColor: \"" + colorStrings.at(j) + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
+ }
+ }
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "Text { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), testColor);
+ }
+}
+QTEST_MAIN(tst_qfxtext)
+
+#include "tst_qfxtext.moc"
diff --git a/tests/auto/declarative/qfxtextedit/qfxtextedit.pro b/tests/auto/declarative/qfxtextedit/qfxtextedit.pro
new file mode 100644
index 0000000..59ab6e5
--- /dev/null
+++ b/tests/auto/declarative/qfxtextedit/qfxtextedit.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+SOURCES += tst_qfxtextedit.cpp
diff --git a/tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp b/tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp
new file mode 100644
index 0000000..7be5b50
--- /dev/null
+++ b/tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp
@@ -0,0 +1,326 @@
+#include <qtest.h>
+#include <QTextDocument>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qfxtextedit.h>
+#include <QFontMetrics>
+
+class tst_qfxtextedit : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qfxtextedit();
+
+private slots:
+ void text();
+ void width();
+ void wrap();
+
+ // ### these tests may be trivial
+ void hAlign();
+ void vAlign();
+ void font();
+ void color();
+
+private:
+ QStringList standard;
+ QStringList richText;
+
+ QStringList hAlignmentStrings;
+ QStringList vAlignmentStrings;
+
+ QList<Qt::Alignment> vAlignments;
+ QList<Qt::Alignment> hAlignments;
+
+ QStringList colorStrings;
+
+ QmlEngine engine;
+};
+
+tst_qfxtextedit::tst_qfxtextedit()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog";
+
+ richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ hAlignmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ vAlignmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ hAlignments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ vAlignments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+void tst_qfxtextedit::text()
+{
+ {
+ QmlComponent texteditComponent(&engine, "TextEdit { text: \"\" }");
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), QString(""));
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "TextEdit { text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), standard.at(i));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "TextEdit { text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QString actual = textEditObject->text();
+ QString expected = richText.at(i);
+ actual.replace(QRegExp(".*<body[^>]*>"),"");
+ actual.replace(QRegExp("(<[^>]*>)+"),"<>");
+ expected.replace(QRegExp("(<[^>]*>)+"),"<>");
+ QCOMPARE(actual.simplified(),expected.simplified());
+ }
+}
+
+void tst_qfxtextedit::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QmlComponent texteditComponent(&engine, "TextEdit { text: \"\" }");
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 0.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ QFontMetrics fm(f);
+ int metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+
+ QString componentStr = "TextEdit { text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), qreal(metricWidth));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QTextDocument document;
+ document.setHtml(richText.at(i));
+ document.setDocumentMargin(0);
+
+ int documentWidth = document.idealWidth();
+
+ QString componentStr = "TextEdit { text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), qreal(documentWidth));
+ }
+}
+
+void tst_qfxtextedit::wrap()
+{
+ // for specified width and wrap set true
+ {
+ QmlComponent texteditComponent(&engine, "TextEdit { text: \"\"; wrap: true; width: 300 }");
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "TextEdit { wrap: true; width: 300; text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "TextEdit { wrap: true; width: 300; text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+}
+
+//the alignment tests may be trivial o.oa
+void tst_qfxtextedit::hAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "TextEdit { hAlign: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "TextEdit { hAlign: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtextedit::vAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "TextEdit { vAlign: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "TextEdit { vAlign: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtextedit::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "TextEdit { font.size: 40; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->size(), qreal(40));
+ QCOMPARE(textEditObject->font()->bold(), false);
+ QCOMPARE(textEditObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "TextEdit { font.bold: true; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->bold(), true);
+ QCOMPARE(textEditObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "TextEdit { font.italic: true; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->italic(), true);
+ QCOMPARE(textEditObject->font()->bold(), false);
+ }
+
+ {
+ QString componentStr = "TextEdit { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->family(), QString("Helvetica"));
+ QCOMPARE(textEditObject->font()->bold(), false);
+ QCOMPARE(textEditObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "TextEdit { font.family: \"\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->family(), QString(""));
+ }
+}
+
+void tst_qfxtextedit::color()
+{
+ //test style
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "TextEdit { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+ //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
+ QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
+ }
+
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "TextEdit { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->color(), testColor);
+ }
+}
+QTEST_MAIN(tst_qfxtextedit)
+
+#include "tst_qfxtextedit.moc"
diff --git a/tests/auto/declarative/qmlbindengine/bindingLoop.txt b/tests/auto/declarative/qmlbindengine/bindingLoop.txt
new file mode 100644
index 0000000..e27a76c
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/bindingLoop.txt
@@ -0,0 +1,12 @@
+MyQmlContainer {
+ children : [
+ MyQmlObject {
+ id: Object1
+ stringProperty: "hello" + Object2.stringProperty
+ },
+ MyQmlObject {
+ id: Object2
+ stringProperty: "hello" + Object1.stringProperty
+ }
+ ]
+}
diff --git a/tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.1.txt b/tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.1.txt
new file mode 100644
index 0000000..7368ff6
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.1.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ stringProperty: trueProperty?'pass':'fail'
+}
diff --git a/tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.2.txt b/tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.2.txt
new file mode 100644
index 0000000..c74493e
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/boolPropertiesEvaluateAsBool.2.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ stringProperty: falseProperty?'fail':'pass'
+}
diff --git a/tests/auto/declarative/qmlbindengine/idShortcutInvalidates.1.txt b/tests/auto/declarative/qmlbindengine/idShortcutInvalidates.1.txt
new file mode 100644
index 0000000..2687465
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/idShortcutInvalidates.1.txt
@@ -0,0 +1,10 @@
+MyQmlObject {
+ objectProperty: if(1) OtherObject
+
+ property var obj
+
+ obj: Object {
+ id: OtherObject
+ }
+}
+
diff --git a/tests/auto/declarative/qmlbindengine/idShortcutInvalidates.txt b/tests/auto/declarative/qmlbindengine/idShortcutInvalidates.txt
new file mode 100644
index 0000000..4aa20ae
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/idShortcutInvalidates.txt
@@ -0,0 +1,9 @@
+MyQmlObject {
+ objectProperty: OtherObject
+
+ property var obj
+
+ obj: Object {
+ id: OtherObject
+ }
+}
diff --git a/tests/auto/declarative/qmlbindengine/methods.1.txt b/tests/auto/declarative/qmlbindengine/methods.1.txt
new file mode 100644
index 0000000..35279e0
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/methods.1.txt
@@ -0,0 +1,4 @@
+MyQmlObject {
+ id: MyObject
+ onBasicSignal: MyObject.method()
+}
diff --git a/tests/auto/declarative/qmlbindengine/methods.2.txt b/tests/auto/declarative/qmlbindengine/methods.2.txt
new file mode 100644
index 0000000..352913a
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/methods.2.txt
@@ -0,0 +1,4 @@
+MyQmlObject {
+ id: MyObject
+ onBasicSignal: MyObject.method(163)
+}
diff --git a/tests/auto/declarative/qmlbindengine/qmlbindengine.pro b/tests/auto/declarative/qmlbindengine/qmlbindengine.pro
new file mode 100644
index 0000000..4a38ac9
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/qmlbindengine.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+SOURCES += tst_qmlbindengine.cpp \
+ testtypes.cpp
+HEADERS += testtypes.h
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
diff --git a/tests/auto/declarative/qmlbindengine/signalAssignment.1.txt b/tests/auto/declarative/qmlbindengine/signalAssignment.1.txt
new file mode 100644
index 0000000..ca682fa
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/signalAssignment.1.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ onBasicSignal: setString('pass')
+}
diff --git a/tests/auto/declarative/qmlbindengine/signalAssignment.2.txt b/tests/auto/declarative/qmlbindengine/signalAssignment.2.txt
new file mode 100644
index 0000000..5efd583
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/signalAssignment.2.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ onArgumentSignal: setString('pass ' + a + ' ' + b + ' ' + c)
+}
diff --git a/tests/auto/declarative/qmlbindengine/testtypes.cpp b/tests/auto/declarative/qmlbindengine/testtypes.cpp
new file mode 100644
index 0000000..4bb0dc8
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/testtypes.cpp
@@ -0,0 +1,4 @@
+#include "testtypes.h"
+
+QML_DEFINE_TYPE(MyQmlObject,MyQmlObject);
+QML_DEFINE_TYPE(MyQmlContainer,MyQmlContainer);
diff --git a/tests/auto/declarative/qmlbindengine/testtypes.h b/tests/auto/declarative/qmlbindengine/testtypes.h
new file mode 100644
index 0000000..6a4bda6
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/testtypes.h
@@ -0,0 +1,127 @@
+#ifndef TESTTYPES_H
+#define TESTTYPES_H
+
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlexpression.h>
+
+class MyQmlObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool trueProperty READ trueProperty)
+ Q_PROPERTY(bool falseProperty READ falseProperty)
+ Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged)
+ Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged);
+public:
+ MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false), m_object(0) {}
+
+ bool trueProperty() const { return true; }
+ bool falseProperty() const { return false; }
+
+ QString stringProperty() const { return m_string; }
+ void setStringProperty(const QString &s)
+ {
+ if (s == m_string)
+ return;
+ m_string = s;
+ emit stringChanged();
+ }
+
+ QObject *objectProperty() const { return m_object; }
+ void setObjectProperty(QObject *obj) {
+ if (obj == m_object)
+ return;
+ m_object = obj;
+ emit objectChanged();
+ }
+
+ bool methodCalled() const { return m_methodCalled; }
+ bool methodIntCalled() const { return m_methodIntCalled; }
+
+ QString string() const { return m_string; }
+signals:
+ void basicSignal();
+ void argumentSignal(int a, QString b, qreal c);
+ void stringChanged();
+ void objectChanged();
+
+public slots:
+ void method() { m_methodCalled = true; }
+ void method(int a) { if(a == 163) m_methodIntCalled = true; }
+ void setString(const QString &s) { m_string = s; }
+
+private:
+ friend class tst_qmlbindengine;
+ bool m_methodCalled;
+ bool m_methodIntCalled;
+
+ QObject *m_object;
+ QString m_string;
+};
+
+QML_DECLARE_TYPE(MyQmlObject);
+
+class MyQmlContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<MyQmlContainer*>* children READ children)
+public:
+ MyQmlContainer() {}
+
+ QList<MyQmlContainer*> *children() { return &m_children; }
+
+private:
+ QList<MyQmlContainer*> m_children;
+};
+
+QML_DECLARE_TYPE(MyQmlContainer);
+
+class MyExpression : public QmlExpression
+{
+public:
+ MyExpression(QmlContext *ctxt, const QString &expr)
+ : QmlExpression(ctxt, expr, 0), changed(false)
+ {
+ }
+
+ virtual void valueChanged() {
+ changed = true;
+ }
+ bool changed;
+};
+
+
+class MyDefaultObject1 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int horseLegs READ horseLegs);
+ Q_PROPERTY(int antLegs READ antLegs);
+public:
+ int horseLegs() const { return 4; }
+ int antLegs() const { return 6; }
+};
+
+class MyDefaultObject2 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int antLegs READ antLegs);
+ Q_PROPERTY(int emuLegs READ emuLegs);
+public:
+ int antLegs() const { return 5; } // Had an accident
+ int emuLegs() const { return 2; }
+};
+
+class MyDefaultObject3 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int antLegs READ antLegs);
+ Q_PROPERTY(int humanLegs READ humanLegs);
+public:
+ int antLegs() const { return 7; } // Mutant
+ int humanLegs() const { return 2; }
+ int millipedeLegs() const { return 1000; }
+};
+
+
+#endif // TESTTYPES_H
+
diff --git a/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp b/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp
new file mode 100644
index 0000000..a1efc5f
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp
@@ -0,0 +1,342 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qdir.h>
+#include "testtypes.h"
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ QFileInfo fileInfo(__FILE__);
+ return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(filename));
+}
+
+inline QUrl TEST_FILE(const char *filename)
+{
+ return TEST_FILE(QLatin1String(filename));
+}
+
+class tst_qmlbindengine : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlbindengine() {}
+
+private slots:
+ void idShortcutInvalidates();
+ void boolPropertiesEvaluateAsBool();
+ void methods();
+ void signalAssignment();
+ void bindingLoop();
+ void basicExpressions();
+ void basicExpressions_data();
+ void arrayExpressions();
+ void contextPropertiesTriggerReeval();
+ void objectPropertiesTriggerReeval();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_qmlbindengine::idShortcutInvalidates()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("idShortcutInvalidates.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->objectProperty() != 0);
+ delete object->objectProperty();
+ QVERIFY(object->objectProperty() == 0);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->objectProperty() != 0);
+ delete object->objectProperty();
+ QVERIFY(object->objectProperty() == 0);
+ }
+}
+
+void tst_qmlbindengine::boolPropertiesEvaluateAsBool()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ }
+ {
+ QmlComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ }
+}
+
+void tst_qmlbindengine::signalAssignment()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("signalAssignment.1.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->string(), QString());
+ emit object->basicSignal();
+ QCOMPARE(object->string(), QString("pass"));
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("signalAssignment.2.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->string(), QString());
+ emit object->argumentSignal(19, "Hello world!", 10.3);
+ QCOMPARE(object->string(), QString("pass 19 Hello world! 10.3"));
+ }
+}
+
+void tst_qmlbindengine::methods()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("methods.1.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), false);
+ emit object->basicSignal();
+ QCOMPARE(object->methodCalled(), true);
+ QCOMPARE(object->methodIntCalled(), false);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("methods.2.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), false);
+ emit object->basicSignal();
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), true);
+ }
+}
+
+void tst_qmlbindengine::bindingLoop()
+{
+ QmlComponent component(&engine, TEST_FILE("bindingLoop.txt"));
+ QTest::ignoreMessage(QtWarningMsg, "QML MyQmlObject (unknown location): Binding loop detected for property \"stringProperty\" ");
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+void tst_qmlbindengine::basicExpressions_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addColumn<QVariant>("result");
+ QTest::addColumn<bool>("nest");
+
+ QTest::newRow("Context property") << "a" << QVariant(1944) << false;
+ QTest::newRow("Context property") << "a" << QVariant(1944) << true;
+ QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
+ QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
+ QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
+ QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
+ QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
+ QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
+ QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
+ QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
+ QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
+ QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
+ QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
+ QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
+ QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
+ QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
+ QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
+ QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
+}
+
+void tst_qmlbindengine::basicExpressions()
+{
+ QFETCH(QString, expression);
+ QFETCH(QVariant, result);
+ QFETCH(bool, nest);
+
+ MyQmlObject object1;
+ MyQmlObject object2;
+ MyQmlObject object3;
+ MyDefaultObject1 default1;
+ MyDefaultObject2 default2;
+ MyDefaultObject3 default3;
+ object1.setStringProperty("Object1");
+ object2.setStringProperty("Object2");
+ object3.setStringProperty("Object3");
+
+ QmlContext context(engine.rootContext());
+ QmlContext nestedContext(&context);
+
+ context.addDefaultObject(&default1);
+ context.addDefaultObject(&default2);
+ context.setContextProperty("a", QVariant(1944));
+ context.setContextProperty("b", QVariant("Milk"));
+ context.setContextProperty("object", &object1);
+ context.setContextProperty("objectOverride", &object2);
+ nestedContext.addDefaultObject(&default3);
+ nestedContext.setContextProperty("b", QVariant("Cow"));
+ nestedContext.setContextProperty("objectOverride", &object3);
+ nestedContext.setContextProperty("millipedeLegs", QVariant(100));
+
+ MyExpression expr(nest?&nestedContext:&context, expression);
+ QCOMPARE(expr.value(), result);
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void tst_qmlbindengine::arrayExpressions()
+{
+ QObject obj1;
+ QObject obj2;
+ QObject obj3;
+
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("a", &obj1);
+ context.setContextProperty("b", &obj2);
+ context.setContextProperty("c", &obj3);
+
+ MyExpression expr(&context, "[a, b, c, 10]");
+ QVariant result = expr.value();
+ QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
+ QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
+ QCOMPARE(list.count(), 4);
+ QCOMPARE(list.at(0), &obj1);
+ QCOMPARE(list.at(1), &obj2);
+ QCOMPARE(list.at(2), &obj3);
+ QCOMPARE(list.at(3), (QObject *)0);
+}
+
+// Tests that modifying a context property will reevaluate expressions
+void tst_qmlbindengine::contextPropertiesTriggerReeval()
+{
+ QmlContext context(engine.rootContext());
+ MyQmlObject object1;
+ MyQmlObject object2;
+ MyQmlObject *object3 = new MyQmlObject;
+
+ object1.setStringProperty("Hello");
+ object2.setStringProperty("World");
+
+ context.setContextProperty("testProp", QVariant(1));
+ context.setContextProperty("testObj", &object1);
+ context.setContextProperty("testObj2", object3);
+
+ {
+ MyExpression expr(&context, "testProp + 1");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant(2));
+
+ context.setContextProperty("testProp", QVariant(2));
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant(3));
+ }
+
+ {
+ MyExpression expr(&context, "testProp + testProp + testProp");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant(6));
+
+ context.setContextProperty("testProp", QVariant(4));
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant(12));
+ }
+
+ {
+ MyExpression expr(&context, "testObj.stringProperty");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant("Hello"));
+
+ context.setContextProperty("testObj", &object2);
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant("World"));
+ }
+
+ {
+ MyExpression expr(&context, "testObj.stringProperty /**/");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant("World"));
+
+ context.setContextProperty("testObj", &object1);
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant("Hello"));
+ }
+
+ {
+ MyExpression expr(&context, "testObj2");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant::fromValue((QObject *)object3));
+
+ delete object3;
+
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant());
+ }
+
+}
+
+void tst_qmlbindengine::objectPropertiesTriggerReeval()
+{
+ QmlContext context(engine.rootContext());
+ MyQmlObject object1;
+ MyQmlObject object2;
+ MyQmlObject object3;
+ context.setContextProperty("testObj", &object1);
+
+ object1.setStringProperty(QLatin1String("Hello"));
+ object2.setStringProperty(QLatin1String("Dog"));
+ object3.setStringProperty(QLatin1String("Cat"));
+
+ {
+ MyExpression expr(&context, "testObj.stringProperty");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant("Hello"));
+
+ object1.setStringProperty(QLatin1String("World"));
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant("World"));
+ }
+
+ {
+ MyExpression expr(&context, "testObj.objectProperty.stringProperty");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant());
+
+ object1.setObjectProperty(&object2);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Dog"));
+
+ object1.setObjectProperty(&object3);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Cat"));
+
+ object1.setObjectProperty(0);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant());
+
+ object1.setObjectProperty(&object3);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Cat"));
+
+ object3.setStringProperty("Donkey");
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Donkey"));
+ }
+}
+
+QTEST_MAIN(tst_qmlbindengine)
+
+#include "tst_qmlbindengine.moc"
diff --git a/tests/auto/declarative/qmldom/qmldom.pro b/tests/auto/declarative/qmldom/qmldom.pro
new file mode 100644
index 0000000..d566354
--- /dev/null
+++ b/tests/auto/declarative/qmldom/qmldom.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmldom.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmldom/tst_qmldom.cpp b/tests/auto/declarative/qmldom/tst_qmldom.cpp
new file mode 100644
index 0000000..ca8929d
--- /dev/null
+++ b/tests/auto/declarative/qmldom/tst_qmldom.cpp
@@ -0,0 +1,146 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmldom.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+
+class tst_qmldom : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmldom() {}
+
+private slots:
+ void loadSimple();
+ void loadProperties();
+ void loadChildObject();
+ void loadComposite();
+
+ void testValueSource();
+
+private:
+ QmlEngine engine;
+};
+
+
+void tst_qmldom::loadSimple()
+{
+ QByteArray qml = "Item {}";
+ //QByteArray qml = "<Item/>";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+ QVERIFY(document.errors().isEmpty());
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+ QVERIFY(!rootObject.isComponent());
+ QVERIFY(!rootObject.isCustomType());
+ QVERIFY(rootObject.objectType() == "Item");
+}
+
+void tst_qmldom::loadProperties()
+{
+ QByteArray qml = "Item { id : item; x : 300; visible : true }";
+ //QByteArray qml = "<Item id='item' x='300' visible='true'/>";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+ QVERIFY(rootObject.objectId() == "item");
+ QVERIFY(rootObject.properties().size() == 2);
+
+ QmlDomProperty xProperty = rootObject.property("x");
+ QVERIFY(xProperty.propertyName() == "x");
+ QVERIFY(xProperty.value().isLiteral());
+ QVERIFY(xProperty.value().toLiteral().literal() == "300");
+
+ QmlDomProperty visibleProperty = rootObject.property("visible");
+ QVERIFY(visibleProperty.propertyName() == "visible");
+ QVERIFY(visibleProperty.value().isLiteral());
+ QVERIFY(visibleProperty.value().toLiteral().literal() == "true");
+}
+
+void tst_qmldom::loadChildObject()
+{
+ QByteArray qml = "Item { Item {} }";
+ //QByteArray qml = "<Item> <Item/> </Item>";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QVERIFY(rootItem.properties().size() == 1);
+
+ QmlDomProperty listProperty = rootItem.properties().at(0);
+ QVERIFY(listProperty.isDefaultProperty());
+ QVERIFY(listProperty.value().isList());
+
+ QmlDomList list = listProperty.value().toList();
+ QVERIFY(list.values().size() == 1);
+
+ QmlDomObject childItem = list.values().first().toObject();
+ QVERIFY(childItem.isValid());
+ QVERIFY(childItem.objectType() == "Item");
+}
+
+void tst_qmldom::loadComposite()
+{
+ QFile file(SRCDIR "/top.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, file.readAll(), QUrl::fromLocalFile(file.fileName())));
+ QVERIFY(document.errors().isEmpty());
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QCOMPARE(rootItem.objectType(), QByteArray("MyComponent"));
+ QCOMPARE(rootItem.properties().size(), 2);
+
+ QmlDomProperty widthProperty = rootItem.property("width");
+ QVERIFY(widthProperty.value().isLiteral());
+
+ QmlDomProperty heightProperty = rootItem.property("height");
+ QVERIFY(heightProperty.value().isLiteral());
+}
+
+void tst_qmldom::testValueSource()
+{
+ QByteArray qml = "Rect { height: Follow { spring: 1.4; damping: .15; source: Math.min(Math.max(-130, value*2.2 - 130), 133); }}";
+
+ QmlEngine freshEngine;
+ QmlDomDocument document;
+ QVERIFY(document.load(&freshEngine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QmlDomProperty heightProperty = rootItem.properties().at(0);
+ QVERIFY(heightProperty.propertyName() == "height");
+ QVERIFY(heightProperty.value().isValueSource());
+
+ const QmlDomValueValueSource valueSource = heightProperty.value().toValueSource();
+ QmlDomObject valueSourceObject = valueSource.object();
+ QVERIFY(valueSourceObject.isValid());
+
+ QVERIFY(valueSourceObject.objectType() == "Follow");
+
+ const QmlDomValue springValue = valueSourceObject.property("spring").value();
+ QVERIFY(!springValue.isInvalid());
+ QVERIFY(springValue.isLiteral());
+ QVERIFY(springValue.toLiteral().literal() == "1.4");
+
+ const QmlDomValue sourceValue = valueSourceObject.property("source").value();
+ QVERIFY(!sourceValue.isInvalid());
+ QVERIFY(sourceValue.isBinding());
+ QVERIFY(sourceValue.toBinding().binding() == "Math.min(Math.max(-130, value*2.2 - 130), 133)");
+}
+
+QTEST_MAIN(tst_qmldom)
+
+#include "tst_qmldom.moc"
diff --git a/tests/auto/declarative/qmlengine/qmlengine.pro b/tests/auto/declarative/qmlengine/qmlengine.pro
new file mode 100644
index 0000000..4ac81e9
--- /dev/null
+++ b/tests/auto/declarative/qmlengine/qmlengine.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlengine.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlengine/tst_qmlengine.cpp b/tests/auto/declarative/qmlengine/tst_qmlengine.cpp
new file mode 100644
index 0000000..9a04c61
--- /dev/null
+++ b/tests/auto/declarative/qmlengine/tst_qmlengine.cpp
@@ -0,0 +1,43 @@
+#include <qtest.h>
+#include <QtDeclarative/QmlEngine>
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QUrl>
+
+class tst_qmlengine : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlengine() {}
+
+private slots:
+ void componentSearchPath();
+};
+
+
+void tst_qmlengine::componentSearchPath()
+{
+ QFile file(SRCDIR "/imports.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+
+ QmlEngine engine;
+
+ QList<QUrl> searchPath = engine.componentSearchPath(file.readAll(),
+ QUrl::fromLocalFile(file.fileName()));
+
+ QList<QUrl> expected;
+ expected << QUrl::fromLocalFile(SRCDIR);
+ expected << QUrl::fromLocalFile(file.fileName()).resolved(QUrl("import1"));
+ expected << QUrl::fromLocalFile(file.fileName()).resolved(QUrl("import2"));
+
+ QCOMPARE(searchPath.size(), expected.size());
+ for (int i = 0; i < expected.size(); ++i) {
+ QCOMPARE(searchPath.at(i).toString(QUrl::StripTrailingSlash),
+ expected.at(i).toString(QUrl::StripTrailingSlash));
+ }
+}
+
+QTEST_MAIN(tst_qmlengine)
+
+#include "tst_qmlengine.moc"
diff --git a/tests/auto/declarative/qmllist/qmllist.pro b/tests/auto/declarative/qmllist/qmllist.pro
new file mode 100644
index 0000000..e5558f1
--- /dev/null
+++ b/tests/auto/declarative/qmllist/qmllist.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmllist.cpp
diff --git a/tests/auto/declarative/qmllist/tst_qmllist.cpp b/tests/auto/declarative/qmllist/tst_qmllist.cpp
new file mode 100644
index 0000000..541ca64
--- /dev/null
+++ b/tests/auto/declarative/qmllist/tst_qmllist.cpp
@@ -0,0 +1,38 @@
+#include <qtest.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlprivate.h>
+
+class tst_QmlList : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlList() {}
+
+private slots:
+ void interface();
+};
+
+void tst_QmlList::interface()
+{
+ QmlConcreteList<QObject*> list;
+ QObject *obj = new QObject;
+ obj->setObjectName("foo");
+ list.append(obj);
+ QVERIFY(list.count() == 1);
+ QCOMPARE(list.at(0), obj);
+
+ QmlPrivate::ListInterface *li = (QmlPrivate::ListInterface*)&list;
+
+ void *ptr[1];
+ li->at(0, ptr);
+ QVERIFY(li->count() == 1);
+ QCOMPARE(ptr[0], obj);
+
+ li->removeAt(0);
+ QVERIFY(li->count() == 0);
+ QVERIFY(list.count() == 0);
+}
+
+QTEST_MAIN(tst_QmlList)
+
+#include "tst_qmllist.moc"
diff --git a/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro b/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro
new file mode 100644
index 0000000..4aa0450
--- /dev/null
+++ b/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmllistaccessor.cpp
diff --git a/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp b/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp
new file mode 100644
index 0000000..f5b57ea
--- /dev/null
+++ b/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp
@@ -0,0 +1,61 @@
+#include <qtest.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmllistaccessor.h>
+
+class tst_QmlListAccessor : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlListAccessor() {}
+
+private slots:
+ void qmllist();
+ //void qlist();
+ //void qstringlist();
+};
+
+void tst_QmlListAccessor::qmllist()
+{
+ QmlConcreteList<QObject*> list;
+ QObject *obj = new QObject;
+ list.append(obj);
+ QVERIFY(list.count() == 1);
+ QCOMPARE(list.at(0), obj);
+
+ QmlListAccessor accessor;
+ accessor.setList(qVariantFromValue((QmlList<QObject*>*)&list));
+
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+
+ QVariant v = accessor.at(0);
+ QCOMPARE(qvariant_cast<QObject*>(v), obj);
+
+ accessor.removeAt(3);
+ QVERIFY(accessor.count() == 1);
+
+ accessor.removeAt(0);
+ QVERIFY(accessor.count() == 0);
+
+ accessor.insert(4, qVariantFromValue(obj));
+ QVERIFY(accessor.count() == 1);
+
+ v = accessor.at(0);
+ QCOMPARE(qvariant_cast<QObject*>(v), obj);
+
+ QObject *obj2 = new QObject;
+ accessor.append(qVariantFromValue(obj2));
+ QVERIFY(accessor.count() == 2);
+
+ v = accessor.at(1);
+ QCOMPARE(qvariant_cast<QObject*>(v), obj2);
+
+ accessor.clear();
+ QVERIFY(accessor.count() == 0);
+
+ QVERIFY(accessor.isValid());
+}
+
+QTEST_MAIN(tst_QmlListAccessor)
+
+#include "tst_qmllistaccessor.moc"
diff --git a/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro b/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro
new file mode 100644
index 0000000..af67373
--- /dev/null
+++ b/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlmetaproperty.cpp
diff --git a/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp
new file mode 100644
index 0000000..e35a006
--- /dev/null
+++ b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp
@@ -0,0 +1,104 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtGui/QLineEdit>
+
+class MyQmlObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyQmlObject() {}
+};
+
+QML_DECLARE_TYPE(MyQmlObject);
+QML_DEFINE_TYPE(MyQmlObject,MyQmlObject);
+
+class MyContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<MyQmlObject*>* children READ children)
+ Q_PROPERTY(QmlList<MyQmlObject*>* qmlChildren READ qmlChildren)
+public:
+ MyContainer() {}
+
+ QList<MyQmlObject*> *children() { return &m_children; }
+ QmlConcreteList<MyQmlObject *> *qmlChildren() { return &m_qmlChildren; }
+
+private:
+ QList<MyQmlObject*> m_children;
+ QmlConcreteList<MyQmlObject *> m_qmlChildren;
+};
+
+QML_DECLARE_TYPE(MyContainer);
+QML_DEFINE_TYPE(MyContainer,MyContainer);
+
+class tst_QmlMetaProperty : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlMetaProperty() {}
+
+private slots:
+ void writeObjectToList();
+ void writeListToList();
+ void writeObjectToQmlList();
+
+ //writeToReadOnly();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_QmlMetaProperty::writeObjectToList()
+{
+ QmlComponent containerComponent(&engine, "MyContainer { children: MyQmlObject {} }");
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->children()->size() == 1);
+
+ MyQmlObject *object = new MyQmlObject;
+ QmlMetaProperty prop(container, "children");
+ prop.write(qVariantFromValue(object));
+ QCOMPARE(container->children()->size(), 2);
+ QCOMPARE(container->children()->at(1), object);
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void tst_QmlMetaProperty::writeListToList()
+{
+ QmlComponent containerComponent(&engine, "MyContainer { children: MyQmlObject {} }");
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->children()->size() == 1);
+
+ QList<QObject*> objList;
+ objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
+ QmlMetaProperty prop(container, "children");
+ prop.write(qVariantFromValue(objList));
+ QCOMPARE(container->children()->size(), 4);
+
+ //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
+ /*QList<MyQmlObject*> typedObjList;
+ typedObjList << new MyQmlObject();
+ prop.write(qVariantFromValue(&typedObjList));
+ QCOMPARE(container->children()->size(), 1);*/
+}
+
+void tst_QmlMetaProperty::writeObjectToQmlList()
+{
+ QmlComponent containerComponent(&engine, "MyContainer { qmlChildren: MyQmlObject {} }");
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qmlChildren()->size() == 1);
+
+ MyQmlObject *object = new MyQmlObject;
+ QmlMetaProperty prop(container, "qmlChildren");
+ prop.write(qVariantFromValue(object));
+ QCOMPARE(container->qmlChildren()->size(), 2);
+ QCOMPARE(container->qmlChildren()->at(1), object);
+}
+
+QTEST_MAIN(tst_QmlMetaProperty)
+
+#include "tst_qmlmetaproperty.moc"
diff --git a/tests/auto/declarative/qmlparser/FailingComponent.qml b/tests/auto/declarative/qmlparser/FailingComponent.qml
new file mode 100644
index 0000000..b604e0b
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/FailingComponent.qml
@@ -0,0 +1,3 @@
+Object {
+ a: 10
+}
diff --git a/tests/auto/declarative/qmlparser/MyComponent.qml b/tests/auto/declarative/qmlparser/MyComponent.qml
new file mode 100644
index 0000000..8a9f57d
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/MyComponent.qml
@@ -0,0 +1,4 @@
+MyQmlObject {
+ property real x;
+ property real y;
+}
diff --git a/tests/auto/declarative/qmlparser/MyContainerComponent.qml b/tests/auto/declarative/qmlparser/MyContainerComponent.qml
new file mode 100644
index 0000000..5746928
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/MyContainerComponent.qml
@@ -0,0 +1,3 @@
+MyContainer {
+ property int x
+}
diff --git a/tests/auto/declarative/qmlparser/assignBasicTypes.txt b/tests/auto/declarative/qmlparser/assignBasicTypes.txt
new file mode 100644
index 0000000..71e400d
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/assignBasicTypes.txt
@@ -0,0 +1,25 @@
+MyTypeObject {
+ flagProperty: "FlagVal1 | FlagVal3"
+ enumProperty: "EnumVal2"
+ stringProperty: "Hello World!"
+ uintProperty: 10
+ intProperty: -19
+ realProperty: 23.2
+ doubleProperty: -19.7
+ colorProperty: "red"
+ dateProperty: "1982-11-25"
+ timeProperty: "11:11:31"
+ timeProperty: "11:11:32"
+ timeProperty: "11:11:32"
+ dateTimeProperty: "2009-05-12T13:22:01"
+ pointProperty: "99,13"
+ pointFProperty: "-10.1,12.3"
+ sizeProperty: "99x13"
+ sizeFProperty: "0.1x0.2"
+ rectProperty: "9,7,100x200"
+ rectFProperty: "1000.1,-10.9,400x90.99"
+ boolProperty: true
+ variantProperty: "Hello World!"
+
+ objectProperty: MyTypeObject { intProperty: 8 }
+}
diff --git a/tests/auto/declarative/qmlparser/assignLiteralSignalProperty.txt b/tests/auto/declarative/qmlparser/assignLiteralSignalProperty.txt
new file mode 100644
index 0000000..f3a7ac7
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/assignLiteralSignalProperty.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ onLiteralSignal: 10
+}
diff --git a/tests/auto/declarative/qmlparser/assignObjectToSignal.txt b/tests/auto/declarative/qmlparser/assignObjectToSignal.txt
new file mode 100644
index 0000000..0d6bc4e
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/assignObjectToSignal.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ onBasicSignal: MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmlparser/assignObjectToVariant.txt b/tests/auto/declarative/qmlparser/assignObjectToVariant.txt
new file mode 100644
index 0000000..180221d
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/assignObjectToVariant.txt
@@ -0,0 +1,4 @@
+Object {
+ property var a;
+ a: MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmlparser/assignQmlComponent.txt b/tests/auto/declarative/qmlparser/assignQmlComponent.txt
new file mode 100644
index 0000000..6b6d77f
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/assignQmlComponent.txt
@@ -0,0 +1,3 @@
+MyContainer {
+ MyComponent { x: 10; y: 11; }
+}
diff --git a/tests/auto/declarative/qmlparser/assignSignal.txt b/tests/auto/declarative/qmlparser/assignSignal.txt
new file mode 100644
index 0000000..6c0fd54
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/assignSignal.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ onBasicSignal: basicSlot()
+}
diff --git a/tests/auto/declarative/qmlparser/assignTypeExtremes.txt b/tests/auto/declarative/qmlparser/assignTypeExtremes.txt
new file mode 100644
index 0000000..dbd281a
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/assignTypeExtremes.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ uintProperty: 4000000000
+ intProperty: -2000000000
+}
diff --git a/tests/auto/declarative/qmlparser/attachedProperties.txt b/tests/auto/declarative/qmlparser/attachedProperties.txt
new file mode 100644
index 0000000..bfe5733
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/attachedProperties.txt
@@ -0,0 +1,3 @@
+Object {
+ MyQmlObject.value: 10
+}
diff --git a/tests/auto/declarative/qmlparser/autoComponentCreation.txt b/tests/auto/declarative/qmlparser/autoComponentCreation.txt
new file mode 100644
index 0000000..e0dbbae
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/autoComponentCreation.txt
@@ -0,0 +1,3 @@
+MyTypeObject {
+ componentProperty : MyTypeObject { realProperty: 9 }
+}
diff --git a/tests/auto/declarative/qmlparser/customParserTypes.txt b/tests/auto/declarative/qmlparser/customParserTypes.txt
new file mode 100644
index 0000000..52848fa
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/customParserTypes.txt
@@ -0,0 +1,4 @@
+ListModel {
+ ListElement { a: 10 }
+ ListElement { a: 12 }
+}
diff --git a/tests/auto/declarative/qmlparser/customVariantTypes.txt b/tests/auto/declarative/qmlparser/customVariantTypes.txt
new file mode 100644
index 0000000..dc5031e
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/customVariantTypes.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ customType: "10"
+}
diff --git a/tests/auto/declarative/qmlparser/duplicateIDs.errors.txt b/tests/auto/declarative/qmlparser/duplicateIDs.errors.txt
new file mode 100644
index 0000000..b03f735
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/duplicateIDs.errors.txt
@@ -0,0 +1 @@
+3:5:id is not unique
diff --git a/tests/auto/declarative/qmlparser/duplicateIDs.txt b/tests/auto/declarative/qmlparser/duplicateIDs.txt
new file mode 100644
index 0000000..e76ee21
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/duplicateIDs.txt
@@ -0,0 +1,5 @@
+MyContainer {
+ MyQmlObject { id: MyID }
+ MyQmlObject { id: MyID }
+}
+
diff --git a/tests/auto/declarative/qmlparser/dynamicObject.1.txt b/tests/auto/declarative/qmlparser/dynamicObject.1.txt
new file mode 100644
index 0000000..ac892c3
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/dynamicObject.1.txt
@@ -0,0 +1,6 @@
+SetProperties {
+ propa: a + 10
+ propb: Math.min(a, 10)
+ propc: MyPropertyValueSource {}
+ onPropA: a
+}
diff --git a/tests/auto/declarative/qmlparser/dynamicProperties.txt b/tests/auto/declarative/qmlparser/dynamicProperties.txt
new file mode 100644
index 0000000..14c85a7
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/dynamicProperties.txt
@@ -0,0 +1,11 @@
+Object {
+ default property int intProperty : 10
+ property bool boolProperty: false
+ property double doubleProperty: -10.1
+ property real realProperty: -19.9
+ property string stringProperty: "Hello World!"
+ property color colorProperty: "red"
+ property date dateProperty: "1945-09-02"
+ property var varProperty: "Hello World!"
+ property variant variantProperty: 12
+}
diff --git a/tests/auto/declarative/qmlparser/dynamicSignalsAndSlots.txt b/tests/auto/declarative/qmlparser/dynamicSignalsAndSlots.txt
new file mode 100644
index 0000000..7cf65ee
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/dynamicSignalsAndSlots.txt
@@ -0,0 +1,6 @@
+Object {
+ signal signal1
+ function slot1() {}
+ signal signal2
+ function slot2() {}
+}
diff --git a/tests/auto/declarative/qmlparser/empty.errors.txt b/tests/auto/declarative/qmlparser/empty.errors.txt
new file mode 100644
index 0000000..e0ed268
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/empty.errors.txt
@@ -0,0 +1 @@
+0:0:Expected token `identifier'
diff --git a/tests/auto/declarative/qmlparser/empty.txt b/tests/auto/declarative/qmlparser/empty.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/empty.txt
diff --git a/tests/auto/declarative/qmlparser/failingComponent.errors.txt b/tests/auto/declarative/qmlparser/failingComponent.errors.txt
new file mode 100644
index 0000000..12fb4e7
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/failingComponent.errors.txt
@@ -0,0 +1,2 @@
+-1:-1:Unable to create type FailingComponent
+2:5:Cannot assign value to non-existant property "a"
diff --git a/tests/auto/declarative/qmlparser/failingComponent.txt b/tests/auto/declarative/qmlparser/failingComponent.txt
new file mode 100644
index 0000000..8c43f84
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/failingComponent.txt
@@ -0,0 +1,4 @@
+MyContainer {
+ FailingComponent {}
+}
+
diff --git a/tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt b/tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt
new file mode 100644
index 0000000..a94b38e
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt
@@ -0,0 +1 @@
+2:11:Cannot assign value to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/fakeDotProperty.txt b/tests/auto/declarative/qmlparser/fakeDotProperty.txt
new file mode 100644
index 0000000..28eb9dc
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/fakeDotProperty.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ value.something: "hello"
+}
diff --git a/tests/auto/declarative/qmlparser/idProperty.txt b/tests/auto/declarative/qmlparser/idProperty.txt
new file mode 100644
index 0000000..9c7d6fb
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/idProperty.txt
@@ -0,0 +1,7 @@
+MyContainer {
+ property var object : MyObjectId
+
+ MyTypeObject {
+ id: MyObjectId
+ }
+}
diff --git a/tests/auto/declarative/qmlparser/inlineQmlComponents.txt b/tests/auto/declarative/qmlparser/inlineQmlComponents.txt
new file mode 100644
index 0000000..e713a88
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/inlineQmlComponents.txt
@@ -0,0 +1,8 @@
+MyContainer {
+ Component {
+ id: MyComponent
+ MyQmlObject {
+ value: 11
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlparser/interfaceProperty.txt b/tests/auto/declarative/qmlparser/interfaceProperty.txt
new file mode 100644
index 0000000..cbad7f1
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/interfaceProperty.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ interface: MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmlparser/interfaceQList.txt b/tests/auto/declarative/qmlparser/interfaceQList.txt
new file mode 100644
index 0000000..6c6ab4b
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/interfaceQList.txt
@@ -0,0 +1,6 @@
+MyContainer {
+ qlistInterfaces: [
+ MyQmlObject {},
+ MyQmlObject {}
+ ]
+}
diff --git a/tests/auto/declarative/qmlparser/interfaceQmlList.txt b/tests/auto/declarative/qmlparser/interfaceQmlList.txt
new file mode 100644
index 0000000..f41c105
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/interfaceQmlList.txt
@@ -0,0 +1,6 @@
+MyContainer {
+ qmllistInterfaces: [
+ MyQmlObject {},
+ MyQmlObject {}
+ ]
+}
diff --git a/tests/auto/declarative/qmlparser/invalidID.2.errors.txt b/tests/auto/declarative/qmlparser/invalidID.2.errors.txt
new file mode 100644
index 0000000..6380750
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.2.errors.txt
@@ -0,0 +1,2 @@
+1:1:"" is not a valid id
+
diff --git a/tests/auto/declarative/qmlparser/invalidID.2.txt b/tests/auto/declarative/qmlparser/invalidID.2.txt
new file mode 100644
index 0000000..a7af29e
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.2.txt
@@ -0,0 +1,4 @@
+MyQmlObject {
+ id: ""
+}
+
diff --git a/tests/auto/declarative/qmlparser/invalidID.3.errors.txt b/tests/auto/declarative/qmlparser/invalidID.3.errors.txt
new file mode 100644
index 0000000..05937f0
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.3.errors.txt
@@ -0,0 +1 @@
+2:5:The id property cannot be fetched
diff --git a/tests/auto/declarative/qmlparser/invalidID.3.txt b/tests/auto/declarative/qmlparser/invalidID.3.txt
new file mode 100644
index 0000000..c686914
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.3.txt
@@ -0,0 +1,4 @@
+MyQmlObject {
+ id.other: 10
+}
+
diff --git a/tests/auto/declarative/qmlparser/invalidID.4.errors.txt b/tests/auto/declarative/qmlparser/invalidID.4.errors.txt
new file mode 100644
index 0000000..50c8960
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.4.errors.txt
@@ -0,0 +1 @@
+3:5:The object id may only be set once
diff --git a/tests/auto/declarative/qmlparser/invalidID.4.txt b/tests/auto/declarative/qmlparser/invalidID.4.txt
new file mode 100644
index 0000000..734ccc4
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.4.txt
@@ -0,0 +1,5 @@
+MyQmlObject {
+ id: Hello
+ id: World
+}
+
diff --git a/tests/auto/declarative/qmlparser/invalidID.errors.txt b/tests/auto/declarative/qmlparser/invalidID.errors.txt
new file mode 100644
index 0000000..eed1869
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.errors.txt
@@ -0,0 +1 @@
+1:1:"1" is not a valid id
diff --git a/tests/auto/declarative/qmlparser/invalidID.txt b/tests/auto/declarative/qmlparser/invalidID.txt
new file mode 100644
index 0000000..f91e8c4
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/invalidID.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ id: 1
+}
diff --git a/tests/auto/declarative/qmlparser/listAssignment.1.errors.txt b/tests/auto/declarative/qmlparser/listAssignment.1.errors.txt
new file mode 100644
index 0000000..44a275b
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/listAssignment.1.errors.txt
@@ -0,0 +1 @@
+1:1:Cannot assign primitives to lists
diff --git a/tests/auto/declarative/qmlparser/listAssignment.1.txt b/tests/auto/declarative/qmlparser/listAssignment.1.txt
new file mode 100644
index 0000000..e2376f2
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/listAssignment.1.txt
@@ -0,0 +1,3 @@
+MyContainer {
+ qmllistInterfaces: 1
+}
diff --git a/tests/auto/declarative/qmlparser/listAssignment.2.errors.txt b/tests/auto/declarative/qmlparser/listAssignment.2.errors.txt
new file mode 100644
index 0000000..572d662
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/listAssignment.2.errors.txt
@@ -0,0 +1,2 @@
+1:1:Cannot assign primitives to lists
+
diff --git a/tests/auto/declarative/qmlparser/listAssignment.2.txt b/tests/auto/declarative/qmlparser/listAssignment.2.txt
new file mode 100644
index 0000000..375e4b4
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/listAssignment.2.txt
@@ -0,0 +1,3 @@
+MyContainer {
+ children: 2
+}
diff --git a/tests/auto/declarative/qmlparser/listAssignment.3.errors.txt b/tests/auto/declarative/qmlparser/listAssignment.3.errors.txt
new file mode 100644
index 0000000..ab6fec8
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/listAssignment.3.errors.txt
@@ -0,0 +1 @@
+1:1:Can only assign one binding to lists
diff --git a/tests/auto/declarative/qmlparser/listAssignment.3.txt b/tests/auto/declarative/qmlparser/listAssignment.3.txt
new file mode 100644
index 0000000..b776bee
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/listAssignment.3.txt
@@ -0,0 +1,5 @@
+MyContainer {
+ children: childBinding.expression
+ children: childBinding2.expression
+}
+
diff --git a/tests/auto/declarative/qmlparser/missingObject.errors.txt b/tests/auto/declarative/qmlparser/missingObject.errors.txt
new file mode 100644
index 0000000..8438b9e
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/missingObject.errors.txt
@@ -0,0 +1 @@
+1:10:Syntax error
diff --git a/tests/auto/declarative/qmlparser/missingObject.txt b/tests/auto/declarative/qmlparser/missingObject.txt
new file mode 100644
index 0000000..2f17045
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/missingObject.txt
@@ -0,0 +1 @@
+something: 24
diff --git a/tests/auto/declarative/qmlparser/missingSignal.errors.txt b/tests/auto/declarative/qmlparser/missingSignal.errors.txt
new file mode 100644
index 0000000..5c612cc
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/missingSignal.errors.txt
@@ -0,0 +1 @@
+2:5:Cannot assign binding to non-existant property "onClicked"
diff --git a/tests/auto/declarative/qmlparser/missingSignal.txt b/tests/auto/declarative/qmlparser/missingSignal.txt
new file mode 100644
index 0000000..07d1bfa
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/missingSignal.txt
@@ -0,0 +1,3 @@
+Object {
+ onClicked: print("Hello world!")
+}
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt
new file mode 100644
index 0000000..e8f1a91
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt
@@ -0,0 +1 @@
+1:15:Cannot assign value to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.1.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.1.txt
new file mode 100644
index 0000000..5023b38
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.1.txt
@@ -0,0 +1 @@
+MyQmlObject { something: 24 }
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt
new file mode 100644
index 0000000..c154f91
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt
@@ -0,0 +1 @@
+2:5:Cannot assign value to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.2.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.2.txt
new file mode 100644
index 0000000..3b6cfa6
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.2.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ something: 24
+}
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt
new file mode 100644
index 0000000..a254d7d
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt
@@ -0,0 +1 @@
+2:5:Cannot assign binding to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.3.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.3.txt
new file mode 100644
index 0000000..61f3625
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.3.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ something: 1 + 1
+}
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt
new file mode 100644
index 0000000..a254d7d
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt
@@ -0,0 +1 @@
+2:5:Cannot assign binding to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.4.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.4.txt
new file mode 100644
index 0000000..5ee1d3a
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.4.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ something: ;
+}
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.5.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.5.errors.txt
new file mode 100644
index 0000000..4234fca4
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.5.errors.txt
@@ -0,0 +1 @@
+2:5:Unexpected token `numeric literal'
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.5.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.5.txt
new file mode 100644
index 0000000..1dc6985
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.5.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ 24
+}
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt
new file mode 100644
index 0000000..3183b6d
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt
@@ -0,0 +1 @@
+2:-1:Cannot assign to default property
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.6.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.6.txt
new file mode 100644
index 0000000..4940833
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.6.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmlparser/nullDotProperty.errors.txt b/tests/auto/declarative/qmlparser/nullDotProperty.errors.txt
new file mode 100644
index 0000000..8482634
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nullDotProperty.errors.txt
@@ -0,0 +1 @@
+2:-1:Cannot set properties on obj as it is null
diff --git a/tests/auto/declarative/qmlparser/nullDotProperty.txt b/tests/auto/declarative/qmlparser/nullDotProperty.txt
new file mode 100644
index 0000000..5c60c5b
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/nullDotProperty.txt
@@ -0,0 +1,3 @@
+MyDotPropertyObject {
+ obj.value: 1
+}
diff --git a/tests/auto/declarative/qmlparser/propertyValueSource.txt b/tests/auto/declarative/qmlparser/propertyValueSource.txt
new file mode 100644
index 0000000..780f527
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/propertyValueSource.txt
@@ -0,0 +1,3 @@
+MyTypeObject {
+ intProperty : MyPropertyValueSource {}
+}
diff --git a/tests/auto/declarative/qmlparser/qmlparser.pro b/tests/auto/declarative/qmlparser/qmlparser.pro
new file mode 100644
index 0000000..dda5c61
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/qmlparser.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlparser.cpp \
+ testtypes.cpp
+HEADERS = testtypes.h
+macx:CONFIG -= app_bundle
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
diff --git a/tests/auto/declarative/qmlparser/readOnly.1.errors.txt b/tests/auto/declarative/qmlparser/readOnly.1.errors.txt
new file mode 100644
index 0000000..89009ce
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/readOnly.1.errors.txt
@@ -0,0 +1 @@
+2:21:Cannot assign value "Hello World" to the read-only property readOnlyString
diff --git a/tests/auto/declarative/qmlparser/readOnly.1.txt b/tests/auto/declarative/qmlparser/readOnly.1.txt
new file mode 100644
index 0000000..c47fdf3
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/readOnly.1.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ readOnlyString: "Hello World"
+}
diff --git a/tests/auto/declarative/qmlparser/readOnly.2.errors.txt b/tests/auto/declarative/qmlparser/readOnly.2.errors.txt
new file mode 100644
index 0000000..ab27946
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/readOnly.2.errors.txt
@@ -0,0 +1 @@
+2:-1:Cannot assign a binding to read-only property "readOnlyString"
diff --git a/tests/auto/declarative/qmlparser/readOnly.2.txt b/tests/auto/declarative/qmlparser/readOnly.2.txt
new file mode 100644
index 0000000..2b6f733
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/readOnly.2.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ readOnlyString: "Hello" + "World"
+}
diff --git a/tests/auto/declarative/qmlparser/rootAsQmlComponent.txt b/tests/auto/declarative/qmlparser/rootAsQmlComponent.txt
new file mode 100644
index 0000000..8cb57ff
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/rootAsQmlComponent.txt
@@ -0,0 +1,5 @@
+MyContainerComponent {
+ x: 11
+ MyQmlObject {}
+ MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmlparser/simpleBindings.txt b/tests/auto/declarative/qmlparser/simpleBindings.txt
new file mode 100644
index 0000000..78f2503
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/simpleBindings.txt
@@ -0,0 +1,17 @@
+MyTypeObject {
+ id: Me
+ property int v1: 10
+ property int v2: 11
+
+ property int value1
+ property int value2
+ property int value3
+ property int value4
+
+ value1: v1
+ value2: Me.v1
+ value3: v1 + v2
+ value4: Math.min(v1, v2)
+
+ objectProperty: Me
+}
diff --git a/tests/auto/declarative/qmlparser/simpleContainer.txt b/tests/auto/declarative/qmlparser/simpleContainer.txt
new file mode 100644
index 0000000..8b30ed9
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/simpleContainer.txt
@@ -0,0 +1,4 @@
+MyContainer {
+ MyQmlObject {}
+ MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmlparser/simpleObject.txt b/tests/auto/declarative/qmlparser/simpleObject.txt
new file mode 100644
index 0000000..05ed87a
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/simpleObject.txt
@@ -0,0 +1 @@
+MyQmlObject {}
diff --git a/tests/auto/declarative/qmlparser/testtypes.cpp b/tests/auto/declarative/qmlparser/testtypes.cpp
new file mode 100644
index 0000000..69df5c3
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/testtypes.cpp
@@ -0,0 +1,9 @@
+#include "testtypes.h"
+
+QML_DEFINE_INTERFACE(MyInterface);
+QML_DEFINE_TYPE(MyQmlObject,MyQmlObject);
+QML_DEFINE_TYPE(MyTypeObject,MyTypeObject);
+QML_DEFINE_TYPE(MyContainer,MyContainer);
+QML_DEFINE_TYPE(MyPropertyValueSource,MyPropertyValueSource);
+QML_DEFINE_TYPE(MyDotPropertyObject,MyDotPropertyObject);
+
diff --git a/tests/auto/declarative/qmlparser/testtypes.h b/tests/auto/declarative/qmlparser/testtypes.h
new file mode 100644
index 0000000..e124631
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/testtypes.h
@@ -0,0 +1,391 @@
+#ifndef TESTTYPES_H
+#define TESTTYPES_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qdatetime.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qcolor.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlparserstatus.h>
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+
+class MyInterface
+{
+public:
+ MyInterface() : id(913) {}
+ int id;
+};
+Q_DECLARE_INTERFACE(MyInterface, "com.trolltech.Qt.Test.MyInterface");
+QML_DECLARE_INTERFACE(MyInterface);
+
+struct MyCustomVariantType
+{
+ MyCustomVariantType() : a(0) {}
+ int a;
+};
+Q_DECLARE_METATYPE(MyCustomVariantType);
+
+static QVariant myCustomVariantTypeConverter(const QString &data)
+{
+ MyCustomVariantType rv;
+ rv.a = data.toInt();
+ return QVariant::fromValue(rv);
+}
+
+class MyQmlObject : public QObject, public MyInterface, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+ Q_PROPERTY(QString readOnlyString READ readOnlyString)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
+ Q_PROPERTY(QRect rect READ rect WRITE setRect)
+ Q_PROPERTY(QMatrix matrix READ matrix WRITE setMatrix) //assumed to be unsupported by QML
+ Q_PROPERTY(MyInterface *interface READ interface WRITE setInterface)
+ Q_PROPERTY(int onLiteralSignal READ onLiteralSignal WRITE setOnLiteralSignal);
+ Q_PROPERTY(MyCustomVariantType customType READ customType WRITE setCustomType);
+ Q_INTERFACES(MyInterface QmlParserStatus)
+public:
+ MyQmlObject() : m_value(-1), m_interface(0) { qRegisterMetaType<MyCustomVariantType>("MyCustomVariantType"); }
+
+ int value() const { return m_value; }
+ void setValue(int v) { m_value = v; }
+
+ QString readOnlyString() const { return QLatin1String(""); }
+
+ bool enabled() const { return false; }
+ void setEnabled(bool) {}
+
+ QRect rect() const { return QRect(); }
+ void setRect(const QRect&) {}
+
+ QMatrix matrix() const { return QMatrix(); }
+ void setMatrix(const QMatrix&) {}
+
+ MyInterface *interface() const { return m_interface; }
+ void setInterface(MyInterface *iface) { m_interface = iface; }
+
+ static MyQmlObject *qmlAttachedProperties(QObject *other) {
+ MyQmlObject *rv = new MyQmlObject;
+ rv->setParent(other);
+ return rv;
+ }
+ Q_CLASSINFO("DefaultMethod", "basicSlot()");
+
+ int onLiteralSignal() const { return m_value; }
+ void setOnLiteralSignal(int v) { m_value = v; }
+
+ MyCustomVariantType customType() const { return m_custom; }
+ void setCustomType(const MyCustomVariantType &v) { m_custom = v; }
+public slots:
+ void basicSlot() { qWarning("MyQmlObject::basicSlot"); }
+
+signals:
+ void basicSignal();
+
+private:
+ friend class tst_qmlparser;
+ int m_value;
+ MyInterface *m_interface;
+ MyCustomVariantType m_custom;
+};
+QML_DECLARE_TYPE(MyQmlObject);
+
+class MyTypeObject : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(MyEnum)
+ Q_FLAGS(MyFlags)
+
+ Q_PROPERTY(QString id READ id WRITE setId);
+ Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty);
+ Q_PROPERTY(QmlComponent *componentProperty READ componentProperty WRITE setComponentProperty);
+ Q_PROPERTY(MyFlags flagProperty READ flagProperty WRITE setFlagProperty);
+ Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty);
+ Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty);
+ Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty);
+ Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty);
+ Q_PROPERTY(qreal realProperty READ realProperty WRITE setRealProperty);
+ Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty);
+ Q_PROPERTY(QColor colorProperty READ colorProperty WRITE setColorProperty);
+ Q_PROPERTY(QDate dateProperty READ dateProperty WRITE setDateProperty);
+ Q_PROPERTY(QTime timeProperty READ timeProperty WRITE setTimeProperty);
+ Q_PROPERTY(QDateTime dateTimeProperty READ dateTimeProperty WRITE setDateTimeProperty);
+ Q_PROPERTY(QPoint pointProperty READ pointProperty WRITE setPointProperty);
+ Q_PROPERTY(QPointF pointFProperty READ pointFProperty WRITE setPointFProperty);
+ Q_PROPERTY(QSize sizeProperty READ sizeProperty WRITE setSizeProperty);
+ Q_PROPERTY(QSizeF sizeFProperty READ sizeFProperty WRITE setSizeFProperty);
+ Q_PROPERTY(QRect rectProperty READ rectProperty WRITE setRectProperty);
+ Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty);
+ Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty);
+ Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty);
+
+public:
+ MyTypeObject()
+ : objectPropertyValue(0), componentPropertyValue(0) {}
+
+ QString idValue;
+ QString id() const {
+ return idValue;
+ }
+ void setId(const QString &v) {
+ idValue = v;
+ }
+
+ QObject *objectPropertyValue;
+ QObject *objectProperty() const {
+ return objectPropertyValue;
+ }
+ void setObjectProperty(QObject *v) {
+ objectPropertyValue = v;
+ }
+
+ QmlComponent *componentPropertyValue;
+ QmlComponent *componentProperty() const {
+ return componentPropertyValue;
+ }
+ void setComponentProperty(QmlComponent *v) {
+ componentPropertyValue = v;
+ }
+
+ enum MyFlag { FlagVal1 = 0x01, FlagVal2 = 0x02, FlagVal3 = 0x04 };
+ Q_DECLARE_FLAGS(MyFlags, MyFlag)
+ MyFlags flagPropertyValue;
+ MyFlags flagProperty() const {
+ return flagPropertyValue;
+ }
+ void setFlagProperty(MyFlags v) {
+ flagPropertyValue = v;
+ }
+
+ enum MyEnum { EnumVal1, EnumVal2 };
+ MyEnum enumPropertyValue;
+ MyEnum enumProperty() const {
+ return enumPropertyValue;
+ }
+ void setEnumProperty(MyEnum v) {
+ enumPropertyValue = v;
+ }
+
+ QString stringPropertyValue;
+ QString stringProperty() const {
+ return stringPropertyValue;
+ }
+ void setStringProperty(const QString &v) {
+ stringPropertyValue = v;
+ }
+
+ uint uintPropertyValue;
+ uint uintProperty() const {
+ return uintPropertyValue;
+ }
+ void setUintProperty(const uint &v) {
+ uintPropertyValue = v;
+ }
+
+ int intPropertyValue;
+ int intProperty() const {
+ return intPropertyValue;
+ }
+ void setIntProperty(const int &v) {
+ intPropertyValue = v;
+ }
+
+ qreal realPropertyValue;
+ qreal realProperty() const {
+ return realPropertyValue;
+ }
+ void setRealProperty(const qreal &v) {
+ realPropertyValue = v;
+ }
+
+ double doublePropertyValue;
+ double doubleProperty() const {
+ return doublePropertyValue;
+ }
+ void setDoubleProperty(const double &v) {
+ doublePropertyValue = v;
+ }
+
+ QColor colorPropertyValue;
+ QColor colorProperty() const {
+ return colorPropertyValue;
+ }
+ void setColorProperty(const QColor &v) {
+ colorPropertyValue = v;
+ }
+
+ QDate datePropertyValue;
+ QDate dateProperty() const {
+ return datePropertyValue;
+ }
+ void setDateProperty(const QDate &v) {
+ datePropertyValue = v;
+ }
+
+ QTime timePropertyValue;
+ QTime timeProperty() const {
+ return timePropertyValue;
+ }
+ void setTimeProperty(const QTime &v) {
+ timePropertyValue = v;
+ }
+
+ QDateTime dateTimePropertyValue;
+ QDateTime dateTimeProperty() const {
+ return dateTimePropertyValue;
+ }
+ void setDateTimeProperty(const QDateTime &v) {
+ dateTimePropertyValue = v;
+ }
+
+ QPoint pointPropertyValue;
+ QPoint pointProperty() const {
+ return pointPropertyValue;
+ }
+ void setPointProperty(const QPoint &v) {
+ pointPropertyValue = v;
+ }
+
+ QPointF pointFPropertyValue;
+ QPointF pointFProperty() const {
+ return pointFPropertyValue;
+ }
+ void setPointFProperty(const QPointF &v) {
+ pointFPropertyValue = v;
+ }
+
+ QSize sizePropertyValue;
+ QSize sizeProperty() const {
+ return sizePropertyValue;
+ }
+ void setSizeProperty(const QSize &v) {
+ sizePropertyValue = v;
+ }
+
+ QSizeF sizeFPropertyValue;
+ QSizeF sizeFProperty() const {
+ return sizeFPropertyValue;
+ }
+ void setSizeFProperty(const QSizeF &v) {
+ sizeFPropertyValue = v;
+ }
+
+ QRect rectPropertyValue;
+ QRect rectProperty() const {
+ return rectPropertyValue;
+ }
+ void setRectProperty(const QRect &v) {
+ rectPropertyValue = v;
+ }
+
+ QRectF rectFPropertyValue;
+ QRectF rectFProperty() const {
+ return rectFPropertyValue;
+ }
+ void setRectFProperty(const QRectF &v) {
+ rectFPropertyValue = v;
+ }
+
+ bool boolPropertyValue;
+ bool boolProperty() const {
+ return boolPropertyValue;
+ }
+ void setBoolProperty(const bool &v) {
+ boolPropertyValue = v;
+ }
+
+ QVariant variantPropertyValue;
+ QVariant variantProperty() const {
+ return variantPropertyValue;
+ }
+ void setVariantProperty(const QVariant &v) {
+ variantPropertyValue = v;
+ }
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
+QML_DECLARE_TYPE(MyTypeObject);
+
+class MyContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<QObject*>* children READ children)
+ Q_PROPERTY(QList<MyInterface*>* qlistInterfaces READ qlistInterfaces)
+ Q_PROPERTY(QmlList<MyInterface*>* qmllistInterfaces READ qmllistInterfaces)
+ Q_CLASSINFO("DefaultProperty", "children");
+public:
+ MyContainer() {}
+
+ QList<QObject*> *children() { return &m_children; }
+ QList<MyInterface *> *qlistInterfaces() { return &m_interfaces; }
+ QmlList<MyInterface *> *qmllistInterfaces() { return &m_qmlinterfaces; }
+ const QmlConcreteList<MyInterface *> &qmllistAccessor() const { return m_qmlinterfaces; }
+
+private:
+ QList<QObject*> m_children;
+ QList<MyInterface *> m_interfaces;
+ QmlConcreteList<MyInterface *> m_qmlinterfaces;
+};
+
+QML_DECLARE_TYPE(MyContainer);
+
+class MyPropertyValueSource : public QmlPropertyValueSource
+{
+ Q_OBJECT
+public:
+ MyPropertyValueSource()
+ : QmlPropertyValueSource(0) {}
+
+ QmlMetaProperty prop;
+ virtual void setTarget(const QmlMetaProperty &p)
+ {
+ prop = p;
+ }
+};
+QML_DECLARE_TYPE(MyPropertyValueSource);
+
+class MyDotPropertyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(MyQmlObject *obj READ obj)
+ Q_PROPERTY(MyQmlObject *readWriteObj READ readWriteObj WRITE setReadWriteObj)
+public:
+ MyDotPropertyObject() : m_rwobj(0), m_ownRWObj(false) {}
+ ~MyDotPropertyObject()
+ {
+ if (m_ownRWObj)
+ delete m_rwobj;
+ }
+
+ MyQmlObject *obj() { return 0; }
+
+ MyQmlObject *readWriteObj()
+ {
+ if (!m_rwobj) {
+ m_rwobj = new MyQmlObject;
+ m_ownRWObj = true;
+ }
+ return m_rwobj;
+ }
+
+ void setReadWriteObj(MyQmlObject *obj)
+ {
+ if (m_ownRWObj) {
+ delete m_rwobj;
+ m_ownRWObj = false;
+ }
+
+ m_rwobj = obj;
+ }
+
+private:
+ MyQmlObject *m_rwobj;
+ bool m_ownRWObj;
+};
+
+QML_DECLARE_TYPE(MyDotPropertyObject);
+
+
+
+#endif // TESTTYPES_H
diff --git a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp
new file mode 100644
index 0000000..cdc2a72
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp
@@ -0,0 +1,440 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdir.h>
+#include "testtypes.h"
+
+class tst_qmlparser : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlparser() {
+ QmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
+ }
+
+private slots:
+
+ void errors_data();
+ void errors();
+
+ void simpleObject();
+ void simpleContainer();
+ void interfaceProperty();
+ void interfaceQmlList();
+ void interfaceQList();
+ void assignObjectToSignal();
+ void assignObjectToVariant();
+ void assignLiteralSignalProperty();
+ void assignQmlComponent();
+ void assignBasicTypes();
+ void assignTypeExtremes();
+ void customParserTypes();
+ void rootAsQmlComponent();
+ void inlineQmlComponents();
+ void idProperty();
+ void assignSignal();
+ void dynamicProperties();
+ void dynamicSignalsAndSlots();
+ void simpleBindings();
+ void autoComponentCreation();
+ void propertyValueSource();
+ void attachedProperties();
+ void dynamicObjects();
+ void customVariantTypes();
+
+ // regression tests for crashes
+ void crash1();
+
+private:
+ QmlEngine engine;
+};
+
+#define VERIFY_ERRORS(errorfile) \
+ if (!errorfile) { \
+ QVERIFY(!component.isError()); \
+ QVERIFY(component.errors().isEmpty()); \
+ } else { \
+ QFile file(errorfile); \
+ QVERIFY(file.open(QIODevice::ReadOnly)); \
+ QByteArray data = file.readAll(); \
+ QList<QByteArray> expected = data.split('\n'); \
+ expected.removeAll(QByteArray("")); \
+ QList<QmlError> errors = component.errors(); \
+ QList<QByteArray> actual; \
+ for (int ii = 0; ii < errors.count(); ++ii) { \
+ const QmlError &error = errors.at(ii); \
+ QByteArray errorStr = QByteArray::number(error.line()) + ":" + \
+ QByteArray::number(error.column()) + ":" + \
+ error.description().toUtf8(); \
+ actual << errorStr; \
+ } \
+ if (qgetenv("DEBUG") != "" && expected != actual) \
+ qWarning() << "Expected:" << expected << "Actual:" << actual; \
+ QCOMPARE(expected, actual); \
+ }
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ QFileInfo fileInfo(__FILE__);
+ return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(filename));
+}
+
+inline QUrl TEST_FILE(const char *filename)
+{
+ return TEST_FILE(QLatin1String(filename));
+}
+
+void tst_qmlparser::errors_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("errorFile");
+ QTest::addColumn<bool>("create");
+
+ QTest::newRow("nonExistantProperty.1") << "nonexistantProperty.1.txt" << "nonexistantProperty.1.errors.txt" << false;
+ QTest::newRow("nonExistantProperty.2") << "nonexistantProperty.2.txt" << "nonexistantProperty.2.errors.txt" << false;
+ QTest::newRow("nonExistantProperty.3") << "nonexistantProperty.3.txt" << "nonexistantProperty.3.errors.txt" << false;
+ QTest::newRow("nonExistantProperty.4") << "nonexistantProperty.4.txt" << "nonexistantProperty.4.errors.txt" << false;
+ QTest::newRow("nonExistantProperty.5") << "nonexistantProperty.5.txt" << "nonexistantProperty.5.errors.txt" << false;
+ QTest::newRow("nonExistantProperty.6") << "nonexistantProperty.6.txt" << "nonexistantProperty.6.errors.txt" << true;
+
+ QTest::newRow("wrongType (string for int)") << "wrongType.1.txt" << "wrongType.1.errors.txt" << false;
+ QTest::newRow("wrongType (int for bool)") << "wrongType.2.txt" << "wrongType.2.errors.txt" << false;
+ QTest::newRow("wrongType (bad rect)") << "wrongType.3.txt" << "wrongType.3.errors.txt" << false;
+
+ QTest::newRow("wrongType (invalid enum)") << "wrongType.4.txt" << "wrongType.4.errors.txt" << false;
+ QTest::newRow("wrongType (int for uint)") << "wrongType.5.txt" << "wrongType.5.errors.txt" << false;
+ QTest::newRow("wrongType (string for real)") << "wrongType.6.txt" << "wrongType.6.errors.txt" << false;
+ QTest::newRow("wrongType (int for color)") << "wrongType.7.txt" << "wrongType.7.errors.txt" << false;
+ QTest::newRow("wrongType (int for date)") << "wrongType.8.txt" << "wrongType.8.errors.txt" << false;
+ QTest::newRow("wrongType (int for time)") << "wrongType.9.txt" << "wrongType.9.errors.txt" << false;
+ QTest::newRow("wrongType (int for datetime)") << "wrongType.10.txt" << "wrongType.10.errors.txt" << false;
+ QTest::newRow("wrongType (string for point)") << "wrongType.11.txt" << "wrongType.11.errors.txt" << false;
+ QTest::newRow("wrongType (color for size)") << "wrongType.12.txt" << "wrongType.12.errors.txt" << false;
+ QTest::newRow("wrongType (number string for int)") << "wrongType.13.txt" << "wrongType.13.errors.txt" << false;
+ QTest::newRow("wrongType (int for string)") << "wrongType.14.txt" << "wrongType.14.errors.txt" << false;
+
+ QTest::newRow("readOnly.1") << "readOnly.1.txt" << "readOnly.1.errors.txt" << false;
+ QTest::newRow("readOnly.2") << "readOnly.2.txt" << "readOnly.2.errors.txt" << true;
+
+ QTest::newRow("listAssignment.1") << "listAssignment.1.txt" << "listAssignment.1.errors.txt" << false;
+ QTest::newRow("listAssignment.2") << "listAssignment.2.txt" << "listAssignment.2.errors.txt" << false;
+ QTest::newRow("listAssignment.3") << "listAssignment.3.txt" << "listAssignment.3.errors.txt" << false;
+
+ QTest::newRow("invalidID.1") << "invalidID.txt" << "invalidID.errors.txt" << false;
+ QTest::newRow("invalidID.2") << "invalidID.2.txt" << "invalidID.2.errors.txt" << false;
+ QTest::newRow("invalidID.3") << "invalidID.3.txt" << "invalidID.3.errors.txt" << false;
+ QTest::newRow("invalidID.4") << "invalidID.4.txt" << "invalidID.4.errors.txt" << false;
+
+ QTest::newRow("unsupportedProperty") << "unsupportedProperty.txt" << "unsupportedProperty.errors.txt" << false;
+ QTest::newRow("nullDotProperty") << "nullDotProperty.txt" << "nullDotProperty.errors.txt" << true;
+ QTest::newRow("fakeDotProperty") << "fakeDotProperty.txt" << "fakeDotProperty.errors.txt" << false;
+ QTest::newRow("duplicateIDs") << "duplicateIDs.txt" << "duplicateIDs.errors.txt" << false;
+ QTest::newRow("unregisteredObject") << "unregisteredObject.txt" << "unregisteredObject.errors.txt" << false;
+ QTest::newRow("empty") << "empty.txt" << "empty.errors.txt" << false;
+ QTest::newRow("missingObject") << "missingObject.txt" << "missingObject.errors.txt" << false;
+ QTest::newRow("failingComponent") << "failingComponent.txt" << "failingComponent.errors.txt" << false;
+ QTest::newRow("missingSignal") << "missingSignal.txt" << "missingSignal.errors.txt" << false;
+}
+
+void tst_qmlparser::errors()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, errorFile);
+ QFETCH(bool, create);
+
+ QmlComponent component(&engine, TEST_FILE(file));
+
+ if(create) {
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ VERIFY_ERRORS(errorFile.toLatin1().constData());
+}
+
+void tst_qmlparser::simpleObject()
+{
+ QmlComponent component(&engine, TEST_FILE("simpleObject.txt"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+void tst_qmlparser::simpleContainer()
+{
+ QmlComponent component(&engine, TEST_FILE("simpleContainer.txt"));
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QCOMPARE(container->children()->count(),2);
+}
+
+void tst_qmlparser::interfaceProperty()
+{
+ QmlComponent component(&engine, TEST_FILE("interfaceProperty.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->interface());
+ QVERIFY(object->interface()->id == 913);
+}
+
+void tst_qmlparser::interfaceQmlList()
+{
+ QmlComponent component(&engine, TEST_FILE("interfaceQmlList.txt"));
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qmllistAccessor().count() == 2);
+ for(int ii = 0; ii < 2; ++ii)
+ QVERIFY(container->qmllistAccessor().at(ii)->id == 913);
+}
+
+void tst_qmlparser::interfaceQList()
+{
+ QmlComponent component(&engine, TEST_FILE("interfaceQList.txt"));
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qlistInterfaces()->count() == 2);
+ for(int ii = 0; ii < 2; ++ii)
+ QVERIFY(container->qlistInterfaces()->at(ii)->id == 913);
+}
+
+void tst_qmlparser::assignObjectToSignal()
+{
+ QmlComponent component(&engine, TEST_FILE("assignObjectToSignal.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
+ emit object->basicSignal();
+}
+
+void tst_qmlparser::assignObjectToVariant()
+{
+ QmlComponent component(&engine, TEST_FILE("assignObjectToVariant.txt"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVariant v = object->property("a");
+ QVERIFY(v.userType() == qMetaTypeId<QObject *>());
+}
+
+void tst_qmlparser::assignLiteralSignalProperty()
+{
+ QmlComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->onLiteralSignal(), 10);
+}
+
+// Test is an external component can be loaded and assigned (to a qlist)
+void tst_qmlparser::assignQmlComponent()
+{
+ QmlComponent component(&engine, TEST_FILE("assignQmlComponent.txt"));
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->children()->count() == 1);
+ QObject *child = object->children()->at(0);
+ QCOMPARE(child->property("x"), QVariant(10));
+ QCOMPARE(child->property("y"), QVariant(11));
+}
+
+// Test literal assignment to all the basic types
+void tst_qmlparser::assignBasicTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("assignBasicTypes.txt"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
+ QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
+ QCOMPARE(object->stringProperty(), QString("Hello World!"));
+ QCOMPARE(object->uintProperty(), uint(10));
+ QCOMPARE(object->intProperty(), -19);
+ QCOMPARE((float)object->realProperty(), float(23.2));
+ QCOMPARE((float)object->doubleProperty(), float(-19.7));
+ QCOMPARE(object->colorProperty(), QColor("red"));
+ QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
+ QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
+ QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
+ QCOMPARE(object->pointProperty(), QPoint(99,13));
+ QCOMPARE(object->pointFProperty(), QPointF((float)-10.1, (float)12.3));
+ QCOMPARE(object->sizeProperty(), QSize(99, 13));
+ QCOMPARE(object->sizeFProperty(), QSizeF((float)0.1, (float)0.2));
+ QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
+ QCOMPARE(object->rectFProperty(), QRectF((float)1000.1, (float)-10.9, (float)400, (float)90.99));
+ QCOMPARE(object->boolProperty(), true);
+ QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
+ QVERIFY(object->objectProperty() != 0);
+ MyTypeObject *child = qobject_cast<MyTypeObject *>(object->objectProperty());
+ QVERIFY(child != 0);
+ QCOMPARE(child->intProperty(), 8);
+}
+
+// Test edge case type assignments
+void tst_qmlparser::assignTypeExtremes()
+{
+ QmlComponent component(&engine, TEST_FILE("assignTypeExtremes.txt"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->uintProperty(), 0xEE6B2800);
+ QCOMPARE(object->intProperty(), -0x77359400);
+}
+
+// Tests that custom parser tyeps can be instantiated
+void tst_qmlparser::customParserTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("customParserTypes.txt"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("count") == QVariant(2));
+}
+
+// Tests that the root item can be a custom component
+void tst_qmlparser::rootAsQmlComponent()
+{
+ QmlComponent component(&engine, TEST_FILE("rootAsQmlComponent.txt"));
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("x"), QVariant(11));
+ QCOMPARE(object->children()->count(), 2);
+}
+
+// Tests that components can be specified inline
+void tst_qmlparser::inlineQmlComponents()
+{
+ QmlComponent component(&engine, TEST_FILE("inlineQmlComponents.txt"));
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->children()->count(), 1);
+ QmlComponent *comp = qobject_cast<QmlComponent *>(object->children()->at(0));
+ QVERIFY(comp != 0);
+ MyQmlObject *compObject = qobject_cast<MyQmlObject *>(comp->create());
+ QVERIFY(compObject != 0);
+ QCOMPARE(compObject->value(), 11);
+}
+
+// Tests that types that have an id property have it set
+void tst_qmlparser::idProperty()
+{
+ QmlComponent component(&engine, TEST_FILE("idProperty.txt"));
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->children()->count(), 1);
+ MyTypeObject *child =
+ qobject_cast<MyTypeObject *>(object->children()->at(0));
+ QVERIFY(child != 0);
+ QCOMPARE(child->id(), QString("MyObjectId"));
+ QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
+}
+
+// Tests that signals can be assigned to
+void tst_qmlparser::assignSignal()
+{
+ QmlComponent component(&engine, TEST_FILE("assignSignal.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
+ emit object->basicSignal();
+}
+
+// Tests the creation and assignment of dynamic properties
+void tst_qmlparser::dynamicProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicProperties.txt"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("intProperty"), QVariant(10));
+ QCOMPARE(object->property("boolProperty"), QVariant(false));
+ QCOMPARE(object->property("doubleProperty"), QVariant((float)-10.1));
+ QCOMPARE(object->property("realProperty"), QVariant((float)-19.9));
+ QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
+ QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
+ QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
+ QCOMPARE(object->property("varProperty"), QVariant("Hello World!"));
+ QCOMPARE(object->property("variantProperty"), QVariant(12));
+}
+
+// Tests the declaration of dynamic signals and slots
+void tst_qmlparser::dynamicSignalsAndSlots()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.txt"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1);
+ QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1);
+ QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1);
+ QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1);
+}
+
+void tst_qmlparser::simpleBindings()
+{
+ QmlComponent component(&engine, TEST_FILE("simpleBindings.txt"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("value1"), QVariant(10));
+ QCOMPARE(object->property("value2"), QVariant(10));
+ QCOMPARE(object->property("value3"), QVariant(21));
+ QCOMPARE(object->property("value4"), QVariant(10));
+ QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object));
+}
+
+void tst_qmlparser::autoComponentCreation()
+{
+ QmlComponent component(&engine, TEST_FILE("autoComponentCreation.txt"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->componentProperty() != 0);
+ MyTypeObject *child = qobject_cast<MyTypeObject *>(object->componentProperty()->create());
+ QVERIFY(child != 0);
+ QCOMPARE(child->realProperty(), qreal(9));
+}
+
+void tst_qmlparser::propertyValueSource()
+{
+ QmlComponent component(&engine, TEST_FILE("propertyValueSource.txt"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QList<QmlPropertyValueSource *> valueSources =
+ object->findChildren<QmlPropertyValueSource *>();
+ QCOMPARE(valueSources.count(), 1);
+ MyPropertyValueSource *valueSource =
+ qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
+ QVERIFY(valueSource != 0);
+ QCOMPARE(valueSource->prop.object(), object);
+ QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
+}
+
+void tst_qmlparser::attachedProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("attachedProperties.txt"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QObject *attached = qmlAttachedPropertiesObject<MyQmlObject>(object);
+ QVERIFY(attached != 0);
+ QCOMPARE(attached->property("value"), QVariant(10));
+}
+
+// Tests non-static object properties
+void tst_qmlparser::dynamicObjects()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicObject.1.txt"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+// Tests the registration of custom variant string converters
+void tst_qmlparser::customVariantTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("customVariantTypes.txt"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->customType().a, 10);
+}
+
+void tst_qmlparser::crash1()
+{
+ QmlComponent component(&engine, "Component {}");
+}
+
+QTEST_MAIN(tst_qmlparser)
+
+#include "tst_qmlparser.moc"
diff --git a/tests/auto/declarative/qmlparser/unregisteredObject.errors.txt b/tests/auto/declarative/qmlparser/unregisteredObject.errors.txt
new file mode 100644
index 0000000..11e4e16
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/unregisteredObject.errors.txt
@@ -0,0 +1 @@
+-1:-1:Type UnregisteredObject unavailable
diff --git a/tests/auto/declarative/qmlparser/unregisteredObject.txt b/tests/auto/declarative/qmlparser/unregisteredObject.txt
new file mode 100644
index 0000000..ff46457
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/unregisteredObject.txt
@@ -0,0 +1 @@
+UnregisteredObject {}
diff --git a/tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt b/tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt
new file mode 100644
index 0000000..a067ecb
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt
@@ -0,0 +1 @@
+2:5:Cannot assign value to property matrix of unknown type
diff --git a/tests/auto/declarative/qmlparser/unsupportedProperty.txt b/tests/auto/declarative/qmlparser/unsupportedProperty.txt
new file mode 100644
index 0000000..bbbd31d
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/unsupportedProperty.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ matrix: "1,0,0,0,1,0,0,0,1"
+}
diff --git a/tests/auto/declarative/qmlparser/wrongType.1.errors.txt b/tests/auto/declarative/qmlparser/wrongType.1.errors.txt
new file mode 100644
index 0000000..8976ee1
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.1.errors.txt
@@ -0,0 +1 @@
+2:12:Cannot assign value "hello" to property value
diff --git a/tests/auto/declarative/qmlparser/wrongType.1.txt b/tests/auto/declarative/qmlparser/wrongType.1.txt
new file mode 100644
index 0000000..281a227
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.1.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ value: "hello"
+}
diff --git a/tests/auto/declarative/qmlparser/wrongType.10.errors.txt b/tests/auto/declarative/qmlparser/wrongType.10.errors.txt
new file mode 100644
index 0000000..562cd6c
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.10.errors.txt
@@ -0,0 +1 @@
+2:23:Cannot assign value "12" to property dateTimeProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.10.txt b/tests/auto/declarative/qmlparser/wrongType.10.txt
new file mode 100644
index 0000000..07a90e0
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.10.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ dateTimeProperty: 12
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.11.errors.txt b/tests/auto/declarative/qmlparser/wrongType.11.errors.txt
new file mode 100644
index 0000000..24d27d5
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.11.errors.txt
@@ -0,0 +1 @@
+2:20:Cannot assign value "apples" to property pointProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.11.txt b/tests/auto/declarative/qmlparser/wrongType.11.txt
new file mode 100644
index 0000000..90a3797
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.11.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ pointProperty: "apples"
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.12.errors.txt b/tests/auto/declarative/qmlparser/wrongType.12.errors.txt
new file mode 100644
index 0000000..b57e70e
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.12.errors.txt
@@ -0,0 +1 @@
+2:19:Cannot assign value "red" to property sizeProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.12.txt b/tests/auto/declarative/qmlparser/wrongType.12.txt
new file mode 100644
index 0000000..c3fa4a0
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.12.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ sizeProperty: "red"
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.13.errors.txt b/tests/auto/declarative/qmlparser/wrongType.13.errors.txt
new file mode 100644
index 0000000..7ff4bf3
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.13.errors.txt
@@ -0,0 +1 @@
+2:12:Cannot assign value "12" to property value
diff --git a/tests/auto/declarative/qmlparser/wrongType.13.txt b/tests/auto/declarative/qmlparser/wrongType.13.txt
new file mode 100644
index 0000000..075ec03
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.13.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ value: "12"
+}
diff --git a/tests/auto/declarative/qmlparser/wrongType.14.errors.txt b/tests/auto/declarative/qmlparser/wrongType.14.errors.txt
new file mode 100644
index 0000000..ec41e01
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.14.errors.txt
@@ -0,0 +1 @@
+2:23:Cannot assign value 10 to property stringProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.14.txt b/tests/auto/declarative/qmlparser/wrongType.14.txt
new file mode 100644
index 0000000..3d39c87
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.14.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ stringProperty: 10
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.2.errors.txt b/tests/auto/declarative/qmlparser/wrongType.2.errors.txt
new file mode 100644
index 0000000..301d258
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.2.errors.txt
@@ -0,0 +1 @@
+2:14:Cannot assign value "5" to property enabled
diff --git a/tests/auto/declarative/qmlparser/wrongType.2.txt b/tests/auto/declarative/qmlparser/wrongType.2.txt
new file mode 100644
index 0000000..cdedf8c
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.2.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ enabled: 5
+}
diff --git a/tests/auto/declarative/qmlparser/wrongType.3.errors.txt b/tests/auto/declarative/qmlparser/wrongType.3.errors.txt
new file mode 100644
index 0000000..3afcc2b
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.3.errors.txt
@@ -0,0 +1 @@
+2:11:Cannot assign value "5,5x10" to property rect
diff --git a/tests/auto/declarative/qmlparser/wrongType.3.txt b/tests/auto/declarative/qmlparser/wrongType.3.txt
new file mode 100644
index 0000000..839e0c7
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.3.txt
@@ -0,0 +1,3 @@
+MyQmlObject {
+ rect: "5,5x10"
+}
diff --git a/tests/auto/declarative/qmlparser/wrongType.4.errors.txt b/tests/auto/declarative/qmlparser/wrongType.4.errors.txt
new file mode 100644
index 0000000..6bf88be
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.4.errors.txt
@@ -0,0 +1 @@
+2:19:Cannot assign value "InvalidEnumName" to property enumProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.4.txt b/tests/auto/declarative/qmlparser/wrongType.4.txt
new file mode 100644
index 0000000..6fa4a9c
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.4.txt
@@ -0,0 +1,3 @@
+MyTypeObject {
+ enumProperty: "InvalidEnumName"
+}
diff --git a/tests/auto/declarative/qmlparser/wrongType.5.errors.txt b/tests/auto/declarative/qmlparser/wrongType.5.errors.txt
new file mode 100644
index 0000000..0e40d84
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.5.errors.txt
@@ -0,0 +1 @@
+2:19:Cannot assign value "-13" to property uintProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.5.txt b/tests/auto/declarative/qmlparser/wrongType.5.txt
new file mode 100644
index 0000000..95b0904
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.5.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ uintProperty: -13
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.6.errors.txt b/tests/auto/declarative/qmlparser/wrongType.6.errors.txt
new file mode 100644
index 0000000..9692997
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.6.errors.txt
@@ -0,0 +1 @@
+2:19:Cannot assign value "Hello" to property realProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.6.txt b/tests/auto/declarative/qmlparser/wrongType.6.txt
new file mode 100644
index 0000000..78351f4
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.6.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ realProperty: "Hello"
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.7.errors.txt b/tests/auto/declarative/qmlparser/wrongType.7.errors.txt
new file mode 100644
index 0000000..f44073a
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.7.errors.txt
@@ -0,0 +1 @@
+2:20:Cannot assign value "12" to property colorProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.7.txt b/tests/auto/declarative/qmlparser/wrongType.7.txt
new file mode 100644
index 0000000..8279ffa
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.7.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ colorProperty: 12
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.8.errors.txt b/tests/auto/declarative/qmlparser/wrongType.8.errors.txt
new file mode 100644
index 0000000..8a45ffb
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.8.errors.txt
@@ -0,0 +1 @@
+2:19:Cannot assign value "12" to property dateProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.8.txt b/tests/auto/declarative/qmlparser/wrongType.8.txt
new file mode 100644
index 0000000..e1cfe9a
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.8.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ dateProperty: 12
+}
+
diff --git a/tests/auto/declarative/qmlparser/wrongType.9.errors.txt b/tests/auto/declarative/qmlparser/wrongType.9.errors.txt
new file mode 100644
index 0000000..cba3339
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.9.errors.txt
@@ -0,0 +1 @@
+2:19:Cannot assign value "12" to property timeProperty
diff --git a/tests/auto/declarative/qmlparser/wrongType.9.txt b/tests/auto/declarative/qmlparser/wrongType.9.txt
new file mode 100644
index 0000000..84dfa66
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/wrongType.9.txt
@@ -0,0 +1,4 @@
+MyTypeObject {
+ timeProperty: 12
+}
+
diff --git a/tests/auto/declarative/repeater/data/repeater.qml b/tests/auto/declarative/repeater/data/repeater.qml
new file mode 100644
index 0000000..2498646
--- /dev/null
+++ b/tests/auto/declarative/repeater/data/repeater.qml
@@ -0,0 +1,18 @@
+Rect {
+ id: container
+ width: 240
+ height: 320
+ color: "white"
+ Repeater {
+ id: repeater
+ width: 240
+ height: 320
+ dataSource: testData
+ Component {
+ Text {
+ y: index*20
+ text: modelData
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/repeater/repeater.pro b/tests/auto/declarative/repeater/repeater.pro
new file mode 100644
index 0000000..0ecd7ee
--- /dev/null
+++ b/tests/auto/declarative/repeater/repeater.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_repeater.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/repeater/tst_repeater.cpp b/tests/auto/declarative/repeater/tst_repeater.cpp
new file mode 100644
index 0000000..0d3ec98
--- /dev/null
+++ b/tests/auto/declarative/repeater/tst_repeater.cpp
@@ -0,0 +1,91 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxrepeater.h>
+#include <qfxtext.h>
+#include <qmlcontext.h>
+
+class tst_QFxRepeater : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxRepeater();
+
+private slots:
+ void stringList();
+
+private:
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id);
+};
+
+tst_QFxRepeater::tst_QFxRepeater()
+{
+}
+
+void tst_QFxRepeater::stringList()
+{
+ QFxView *canvas = createView(SRCDIR "/data/repeater.xml");
+
+ QStringList data;
+ data << "One";
+ data << "Two";
+ data << "Three";
+ data << "Four";
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setProperty("testData", data);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRepeater *repeater = findItem<QFxRepeater>(canvas->root(), "repeater");
+ QVERIFY(repeater != 0);
+
+ QFxItem *container = findItem<QFxItem>(canvas->root(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->children()->count(), data.count() + 1);
+
+ for (int i = 1; i < container->children()->count(); ++i) {
+ QFxText *name = qobject_cast<QFxText*>(container->children()->at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), data.at(i-1));
+ }
+
+ delete canvas;
+}
+
+
+QFxView *tst_QFxRepeater::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setQml(xml, filename);
+
+ return canvas;
+}
+
+template<typename T>
+T *tst_QFxRepeater::findItem(QFxItem *parent, const QString &id)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ if (mo.cast(parent) && (id.isEmpty() || parent->id() == id))
+ return static_cast<T*>(parent);
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = findItem<T>(parent->children()->at(i), id);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxRepeater)
+
+#include "tst_repeater.moc"
diff --git a/tests/auto/declarative/simplecanvasitem/data/test.qml b/tests/auto/declarative/simplecanvasitem/data/test.qml
new file mode 100644
index 0000000..d206a6b
--- /dev/null
+++ b/tests/auto/declarative/simplecanvasitem/data/test.qml
@@ -0,0 +1,58 @@
+Item {
+ width: 320
+ height: 480
+ Rect {
+ color: "blue"
+ x: 20
+ y: 20
+ width: 20
+ height: 20
+ Rect {
+ color: "black"
+ x: 20
+ y: 20
+ width: 10
+ height: 10
+ }
+ }
+ Rect {
+ color: "red"
+ x: 40
+ y: 20
+ width: 20
+ height: 20
+ }
+ Rect {
+ color: "green"
+ x: 60
+ y: 20
+ width: 20
+ height: 20
+ }
+ Rect {
+ color: "yellow"
+ x: 20
+ y: 40
+ width: 20
+ height: 20
+ }
+ Rect {
+ color: "purple"
+ x: 20
+ y: 60
+ width: 20
+ height: 20
+ }
+ Rect {
+ color: "white"
+ x: 40
+ y: 40
+ width: 20
+ height: 20
+ }
+ Rect {
+ anchors.fill: parent
+ color: "gray"
+ z: -1
+ }
+}
diff --git a/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro b/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro
new file mode 100644
index 0000000..114be8e
--- /dev/null
+++ b/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_simplecanvasitem.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp b/tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp
new file mode 100644
index 0000000..cce4df1
--- /dev/null
+++ b/tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp
@@ -0,0 +1,79 @@
+#include <QtTest/QtTest>
+#include <qfxview.h>
+#include <qfxitem.h>
+#include <qsimplecanvasitem.h>
+
+/*
+ Note: this autotest is specifically to test SimpleCanvasItem as a component of
+ Qt Declarative, and therefore will have all items created in XML.
+*/
+class tst_SimpleCanvasItem : public QObject
+{
+ Q_OBJECT
+public:
+ tst_SimpleCanvasItem();
+
+private slots:
+ void test_pos();
+ void test_scenePos();
+private:
+ QFxView *createView(const QString &filename);
+};
+
+tst_SimpleCanvasItem::tst_SimpleCanvasItem()
+{
+}
+
+void tst_SimpleCanvasItem::test_pos()
+{
+ QFxView *canvas = createView(SRCDIR "/data/test.qml");
+ canvas->execute();
+ qApp->processEvents();
+ QSimpleCanvasItem* root = qobject_cast<QSimpleCanvasItem*>(canvas->root());
+ QVERIFY(root);
+
+ QCOMPARE(root->pos(), QPointF(0,0));
+ QCOMPARE(root->children().at(0)->pos(), QPointF(20,20));
+ QCOMPARE(root->children().at(0)->children().at(0)->pos(), QPointF(20,20));
+ QCOMPARE(root->children().at(2)->pos(), QPointF(60,20));
+ QCOMPARE(root->children().at(3)->pos(), QPointF(20,40));
+ QCOMPARE(root->children().at(5)->pos(), QPointF(40,40));
+}
+
+void tst_SimpleCanvasItem::test_scenePos()
+{
+ QFxView *canvas = createView(SRCDIR "/data/test.qml");
+ canvas->execute();
+ qApp->processEvents();
+ QSimpleCanvasItem* root = qobject_cast<QSimpleCanvasItem*>(canvas->root());
+ QVERIFY(root);
+
+#ifdef CANVAS_GL
+ QCOMPARE(root->transform(), QMatrix4x4());
+#else
+ QCOMPARE(root->transform(), QTransform());
+#endif
+ QCOMPARE(root->scenePos(), QPointF(0,0));
+ QCOMPARE(root->children().at(0)->scenePos(), QPointF(20,20));
+ QCOMPARE(root->children().at(0)->children().at(0)->scenePos(), QPointF(40,40));
+ QCOMPARE(root->children().at(2)->scenePos(), QPointF(60,20));
+ QCOMPARE(root->children().at(3)->scenePos(), QPointF(20,40));
+ QCOMPARE(root->children().at(5)->scenePos(), QPointF(40,40));
+}
+
+QFxView *tst_SimpleCanvasItem::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setQml(xml, filename);
+
+ return canvas;
+}
+
+QTEST_MAIN(tst_SimpleCanvasItem)
+
+#include "tst_simplecanvasitem.moc"
diff --git a/tests/auto/declarative/visual/ListView/basic1/basic1.qml b/tests/auto/declarative/visual/ListView/basic1/basic1.qml
new file mode 100644
index 0000000..d9cd030
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/basic1.qml
@@ -0,0 +1,25 @@
+Rect {
+ color: "blue"
+ width: 200
+ height: 300
+ id: Page
+ ListView {
+ anchors.fill: parent
+ delegate: Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ model: ListModel {
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic1/data/raster/image0.png b/tests/auto/declarative/visual/ListView/basic1/data/raster/image0.png
new file mode 100644
index 0000000..f8a4830
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic1/data/raster/manifest.qml b/tests/auto/declarative/visual/ListView/basic1/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic1/test b/tests/auto/declarative/visual/ListView/basic1/test
new file mode 100644
index 0000000..49fcf5a
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/test
@@ -0,0 +1 @@
+basic1.qml
diff --git a/tests/auto/declarative/visual/ListView/basic2/basic2.qml b/tests/auto/declarative/visual/ListView/basic2/basic2.qml
new file mode 100644
index 0000000..e5996cf
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/basic2.qml
@@ -0,0 +1,29 @@
+Rect {
+ color: "blue"
+ width: 200
+ height: 300
+ id: Page
+ Component {
+ id: Delegate
+ Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+ ListView {
+ anchors.fill: parent
+ delegate: Delegate
+ model: ListModel {
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic2/data/raster/image0.png b/tests/auto/declarative/visual/ListView/basic2/data/raster/image0.png
new file mode 100644
index 0000000..f8a4830
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic2/data/raster/manifest.qml b/tests/auto/declarative/visual/ListView/basic2/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic2/test b/tests/auto/declarative/visual/ListView/basic2/test
new file mode 100644
index 0000000..eb79495
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/test
@@ -0,0 +1 @@
+basic2.qml
diff --git a/tests/auto/declarative/visual/ListView/basic3/basic3.qml b/tests/auto/declarative/visual/ListView/basic3/basic3.qml
new file mode 100644
index 0000000..98aa5fb
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/basic3.qml
@@ -0,0 +1,27 @@
+Rect {
+ color: "blue"
+ width: 200
+ height: 300
+ id: Page
+ ListModel {
+ id: Model
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ ListView {
+ anchors.fill: parent
+ model: Model
+ delegate: Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic3/data/raster/image0.png b/tests/auto/declarative/visual/ListView/basic3/data/raster/image0.png
new file mode 100644
index 0000000..f8a4830
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic3/data/raster/manifest.qml b/tests/auto/declarative/visual/ListView/basic3/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic3/test b/tests/auto/declarative/visual/ListView/basic3/test
new file mode 100644
index 0000000..9ec306b
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/test
@@ -0,0 +1 @@
+basic3.qml
diff --git a/tests/auto/declarative/visual/ListView/basic4/basic4.qml b/tests/auto/declarative/visual/ListView/basic4/basic4.qml
new file mode 100644
index 0000000..9e5229a
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/basic4.qml
@@ -0,0 +1,31 @@
+Rect {
+ color: "blue"
+ width: 200
+ height: 300
+ id: Page
+ ListModel {
+ id: Model
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ Component {
+ id: Delegate
+ Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+ ListView {
+ anchors.fill: parent
+ model: Model
+ delegate: Delegate
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic4/data/raster/image0.png b/tests/auto/declarative/visual/ListView/basic4/data/raster/image0.png
new file mode 100644
index 0000000..f8a4830
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic4/data/raster/manifest.qml b/tests/auto/declarative/visual/ListView/basic4/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic4/test b/tests/auto/declarative/visual/ListView/basic4/test
new file mode 100644
index 0000000..2a7f227
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/test
@@ -0,0 +1 @@
+basic4.qml
diff --git a/tests/auto/declarative/visual/bindinganimation/bindinganimation.qml b/tests/auto/declarative/visual/bindinganimation/bindinganimation.qml
new file mode 100644
index 0000000..61cedc2
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/bindinganimation.qml
@@ -0,0 +1,40 @@
+Rect {
+ color: "blue"
+ width: 320
+ height: 240
+ id: Page
+ Rect {
+ id: MyRect
+ width: 100
+ height: 100
+ color: "red"
+ x: 10
+ }
+ states: [
+ State {
+ name: "hello"
+ SetProperty {
+ target: MyRect
+ property: "x"
+ binding: 100
+ }
+ SetProperty {
+ target: MyMouseRegion
+ property: "onClicked"
+ value: "Page.currentState = ''"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "x"
+ }
+ }
+ ]
+ MouseRegion {
+ id: MyMouseRegion
+ anchors.fill: parent
+ onClicked: { Page.state= 'hello' }
+ }
+}
diff --git a/tests/auto/declarative/visual/bindinganimation/data/raster/image0.png b/tests/auto/declarative/visual/bindinganimation/data/raster/image0.png
new file mode 100644
index 0000000..92f8cdd
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/bindinganimation/data/raster/manifest.qml b/tests/auto/declarative/visual/bindinganimation/data/raster/manifest.qml
new file mode 100644
index 0000000..1454949
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/data/raster/manifest.qml
@@ -0,0 +1,86 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+ TestMouse {
+ time: 1296
+ type: 2
+ button: 1
+ buttons: 1
+ globalPos: '87,985'
+ pos: '83,29'
+ }
+ TestMouse {
+ time: 1360
+ type: 3
+ button: 1
+ buttons: 0
+ globalPos: '87,985'
+ pos: '83,29'
+ }
+ TestFrame {
+ time: 1376
+ hash: '7CB5FC371040E587DE9F06CE14A4B29A'
+ }
+ TestFrame {
+ time: 1392
+ hash: 'A5E5DBD179C7E48D34B8107F8CC6B5BE'
+ }
+ TestFrame {
+ time: 1408
+ hash: 'A5E5DBD179C7E48D34B8107F8CC6B5BE'
+ }
+ TestFrame {
+ time: 1424
+ hash: '69FB651AA84E07E4A6DEAA31CB10641B'
+ }
+ TestFrame {
+ time: 1440
+ hash: '3FFC4C4BD282010A359DCEAF2D8496AC'
+ }
+ TestFrame {
+ time: 1456
+ hash: '3FFC4C4BD282010A359DCEAF2D8496AC'
+ }
+ TestFrame {
+ time: 1472
+ hash: 'ADA58B13247A654BBCECF3F254AB797F'
+ }
+ TestFrame {
+ time: 1488
+ hash: 'B314799BC732B6BD8C42A622B720E3D5'
+ }
+ TestFrame {
+ time: 1504
+ hash: 'B314799BC732B6BD8C42A622B720E3D5'
+ }
+ TestFrame {
+ time: 1520
+ hash: '7377569C13CF5DE368B22209AB8AE395'
+ }
+ TestFrame {
+ time: 1536
+ hash: '7C1E4A1F80C68EE57D052A9D7851F937'
+ }
+ TestFrame {
+ time: 1552
+ hash: '7C1E4A1F80C68EE57D052A9D7851F937'
+ }
+ TestFrame {
+ time: 1568
+ hash: '24D6DB9544205075836A86A54B55A820'
+ }
+ TestFrame {
+ time: 1584
+ hash: '24D6DB9544205075836A86A54B55A820'
+ }
+ TestFrame {
+ time: 1600
+ hash: '8A84E4C3E8AD4C6A9A7BD3E1620718C1'
+ }
+ TestFrame {
+ time: 1616
+ hash: 'B8EA544A4EF3B7E0A9E0A7777B55EDC7'
+ }
+}
diff --git a/tests/auto/declarative/visual/bindinganimation/test b/tests/auto/declarative/visual/bindinganimation/test
new file mode 100644
index 0000000..bb59333
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/test
@@ -0,0 +1 @@
+bindinganimation.qml
diff --git a/tests/auto/declarative/visual/colorAnimation/colorAnimation.qml b/tests/auto/declarative/visual/colorAnimation/colorAnimation.qml
new file mode 100644
index 0000000..d351b8c
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/colorAnimation.qml
@@ -0,0 +1,41 @@
+Rect {
+ id: mainrect
+ width: 200; height: 200
+ state: "first"
+ states: [
+ State {
+ name: "first"
+ SetProperty {
+ target: mainrect
+ property: "color"
+ value: "red"
+ }
+ },
+ State {
+ name: "second"
+ SetProperty {
+ target: mainrect
+ property: "color"
+ value: "blue"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "first"
+ toState: "second"
+ reversible: true
+ SequentialAnimation {
+ ColorAnimation {
+ duration: 2000
+ target: mainrect
+ property: "color"
+ }
+ }
+ }
+ ]
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { mainrect.state = 'second' }
+ }
+}
diff --git a/tests/auto/declarative/visual/colorAnimation/data/raster/image0.png b/tests/auto/declarative/visual/colorAnimation/data/raster/image0.png
new file mode 100644
index 0000000..f00a2e2
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/colorAnimation/data/raster/manifest.qml b/tests/auto/declarative/visual/colorAnimation/data/raster/manifest.qml
new file mode 100644
index 0000000..0eb8b12
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/data/raster/manifest.qml
@@ -0,0 +1,522 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+ TestMouse {
+ time: 944
+ type: 2
+ button: 1
+ buttons: 1
+ globalPos: '1789,188'
+ pos: '73,76'
+ }
+ TestMouse {
+ time: 992
+ type: 3
+ button: 1
+ buttons: 0
+ globalPos: '1789,188'
+ pos: '73,76'
+ }
+ TestFrame {
+ time: 1008
+ hash: 'E5BDA0DAF98288CE18DB6CE06EDA3BA0'
+ }
+ TestFrame {
+ time: 1024
+ hash: 'D35008F75B8C992F80FB16BA7203649D'
+ }
+ TestFrame {
+ time: 1040
+ hash: '14F43E0784DDF42EA8550DB88C501BF1'
+ }
+ TestFrame {
+ time: 1056
+ hash: '02276E158B5391480B1BDEAADF1FB903'
+ }
+ TestFrame {
+ time: 1072
+ hash: '35D9513EB97A2C482B7CD197DE910934'
+ }
+ TestFrame {
+ time: 1088
+ hash: 'FAF0FD681E60BB2489099F5DF772B6CD'
+ }
+ TestFrame {
+ time: 1104
+ hash: 'A863D3E346F94785A3A392FDC91526EB'
+ }
+ TestFrame {
+ time: 1120
+ hash: 'FDF328D3F6EB8410DA59A91345E41A44'
+ }
+ TestFrame {
+ time: 1136
+ hash: '83514A3B10D5BE8F6C3B128D0F3E0B1C'
+ }
+ TestFrame {
+ time: 1152
+ hash: 'EAD0EAE76CD00189075964671EFFBAEA'
+ }
+ TestFrame {
+ time: 1168
+ hash: '24D2457FCD51490FDA23071BF9929D12'
+ }
+ TestFrame {
+ time: 1184
+ hash: '1478683446CF543DACBE31D0B76A98A6'
+ }
+ TestFrame {
+ time: 1200
+ hash: '99F7DA1F31FE920F6C02ADD4042AE925'
+ }
+ TestFrame {
+ time: 1216
+ hash: '22DEF892006CF66667770B0F17BAF6C0'
+ }
+ TestFrame {
+ time: 1232
+ hash: '6A36D5A77099BFD58BAF285478FF04E4'
+ }
+ TestFrame {
+ time: 1248
+ hash: '6258150666B59B20AB476724C07FC20C'
+ }
+ TestFrame {
+ time: 1264
+ hash: 'F1636315BC950A6DD400D9C7ED263B88'
+ }
+ TestFrame {
+ time: 1280
+ hash: '18447EA8DC2E8DA956788E5B3CF3790A'
+ }
+ TestFrame {
+ time: 1296
+ hash: '1D2A6E65997A73E9E670356C8E8B63B2'
+ }
+ TestFrame {
+ time: 1312
+ hash: 'BED0242C0F9EF229D1392835286D5782'
+ }
+ TestFrame {
+ time: 1328
+ hash: '88923C190E9E5BEADEF8A409C06DF9D6'
+ }
+ TestFrame {
+ time: 1344
+ hash: '2D133E7EE60C97386F57838B3F0976C7'
+ }
+ TestFrame {
+ time: 1360
+ hash: '85B1821CC50F2A9F3ED6944F792B7A2F'
+ }
+ TestFrame {
+ time: 1376
+ hash: '395195716D76BC0BE7B2033ED37A7A1C'
+ }
+ TestFrame {
+ time: 1392
+ hash: '243DBFFCF416926242BBCB7348974C4C'
+ }
+ TestFrame {
+ time: 1408
+ hash: 'A755068679616D8AC65C2AA7431F2A19'
+ }
+ TestFrame {
+ time: 1424
+ hash: 'E8249B35A47EB492CBDF2D91CC8426F0'
+ }
+ TestFrame {
+ time: 1440
+ hash: '15F3DA1C0E6F0779B96859D51171DD27'
+ }
+ TestFrame {
+ time: 1456
+ hash: '258C0C756AAC3DE743B43051F2AACE6B'
+ }
+ TestFrame {
+ time: 1472
+ hash: 'A58B9FDF301D72B2CC5C93934CC8927B'
+ }
+ TestFrame {
+ time: 1488
+ hash: 'A9181D30870D472521F8904818CE520F'
+ }
+ TestFrame {
+ time: 1504
+ hash: '7F9E94069CCF3897C26A71BD7BECD903'
+ }
+ TestFrame {
+ time: 1520
+ hash: 'BDF305C2F46CDB86DBF57B1E0CC5A65B'
+ }
+ TestFrame {
+ time: 1536
+ hash: 'FE5B6865D7E4FC7D1D42C1E74F8666F7'
+ }
+ TestFrame {
+ time: 1552
+ hash: '734F0DE45A6E34C9EAB7EF606196F96A'
+ }
+ TestFrame {
+ time: 1568
+ hash: '02A361C4534FDF7F286DC3E6DC23275C'
+ }
+ TestFrame {
+ time: 1584
+ hash: 'E649155AD69999C14B92F6561E4D1185'
+ }
+ TestFrame {
+ time: 1600
+ hash: '01AF177084FAB755D622973F64B92018'
+ }
+ TestFrame {
+ time: 1616
+ hash: '097CC4A082DFAB995D213A3A73883C97'
+ }
+ TestFrame {
+ time: 1632
+ hash: 'D7B4239A3280B1EB8E885E3F422DF8E9'
+ }
+ TestFrame {
+ time: 1648
+ hash: '59893977994E34E83F91E7CE3AD65D6D'
+ }
+ TestFrame {
+ time: 1664
+ hash: 'B68E3FBB5CDCD6BD96DF7DEC558DB42B'
+ }
+ TestFrame {
+ time: 1680
+ hash: '94AD0580648F36A1E18A9EA7E249B04D'
+ }
+ TestFrame {
+ time: 1696
+ hash: '750A4C01D2F5806A89A1C6CC6A9B9A68'
+ }
+ TestFrame {
+ time: 1712
+ hash: '4F109F50F388F1BFA4BC6B03B3E6E514'
+ }
+ TestFrame {
+ time: 1728
+ hash: 'C6168D5CF27A533E8EE636637667BE47'
+ }
+ TestFrame {
+ time: 1744
+ hash: 'F8120547BED987AA34C00DA5A01A4D1E'
+ }
+ TestFrame {
+ time: 1760
+ hash: 'CBFF526136FA2C128C8B898FBBEF9E5C'
+ }
+ TestFrame {
+ time: 1776
+ hash: 'F29E52398FAB1A239A63DF4C32F2FC69'
+ }
+ TestFrame {
+ time: 1792
+ hash: '7178BFE86FD2FD513218B33760460F8D'
+ }
+ TestFrame {
+ time: 1808
+ hash: 'CA83285BC8AC633403896FE976896EB0'
+ }
+ TestFrame {
+ time: 1824
+ hash: '96BA486C09CC69D5AA38C46C00DF1181'
+ }
+ TestFrame {
+ time: 1840
+ hash: 'B88EAB335842787869F4A14824C19DD8'
+ }
+ TestFrame {
+ time: 1856
+ hash: '065AA59012729E1E1A246A2083142690'
+ }
+ TestFrame {
+ time: 1872
+ hash: 'DD0E98C8398861002C5F178C5F9F612D'
+ }
+ TestFrame {
+ time: 1888
+ hash: '04192C2B545948048ECCF4D81BBDE198'
+ }
+ TestFrame {
+ time: 1904
+ hash: 'BB7502C7208281EF9FD41714AB88A1A8'
+ }
+ TestFrame {
+ time: 1920
+ hash: '5397195471890D08B703DCA101E5BC7C'
+ }
+ TestFrame {
+ time: 1936
+ hash: '4C678CDBEBB2FFD2CBF012CA77800CDE'
+ }
+ TestFrame {
+ time: 1952
+ hash: '0D7A34ECD0C7F52B2C015037BF1902C6'
+ }
+ TestFrame {
+ time: 1968
+ hash: 'FD9D5048BE749AC4369FDA2D018B43AE'
+ }
+ TestFrame {
+ time: 1984
+ hash: '93EE03795CD57AE6F7FE3A020B039AD4'
+ }
+ TestFrame {
+ time: 2000
+ hash: '5E1118963F219C39761CA7FBF564A9CA'
+ }
+ TestFrame {
+ time: 2016
+ hash: '8F40038741903150136170503649D941'
+ }
+ TestFrame {
+ time: 2032
+ hash: 'B087B7D0AA6224821F8E18718FF5E77D'
+ }
+ TestFrame {
+ time: 2048
+ hash: 'AA46B04A3C67DC772265ED2901955565'
+ }
+ TestFrame {
+ time: 2064
+ hash: 'AC024BF2AEB4BECDF31A09FE0A6DB8F3'
+ }
+ TestFrame {
+ time: 2080
+ hash: '13745A174E4D06E2108A5BF125BA50CC'
+ }
+ TestFrame {
+ time: 2096
+ hash: 'BD972F0D8E230ECA0B3FEA1B8C960C08'
+ }
+ TestFrame {
+ time: 2112
+ hash: 'CBDBEC802A58E7CED0CF45B3AB0BC0BA'
+ }
+ TestFrame {
+ time: 2128
+ hash: '5128584C50305C7D218B81B8367FA3D5'
+ }
+ TestFrame {
+ time: 2144
+ hash: 'A71461D3593F3685620668916DE870BD'
+ }
+ TestFrame {
+ time: 2160
+ hash: '74EBAC8F32CF044B58D9883DBCD9A722'
+ }
+ TestFrame {
+ time: 2176
+ hash: 'FEDC5B638F339B90FE59B478721E65B7'
+ }
+ TestFrame {
+ time: 2192
+ hash: 'BCB8C7159F54C353551DD3BFF3203966'
+ }
+ TestFrame {
+ time: 2208
+ hash: '4E9B083075BC5E9287A8ABC982778B56'
+ }
+ TestFrame {
+ time: 2224
+ hash: '1D6F02AA99AFA47D77FC49AB894B365A'
+ }
+ TestFrame {
+ time: 2240
+ hash: 'A204FEEC783B3B05DE4C209C21745826'
+ }
+ TestFrame {
+ time: 2256
+ hash: '665A2A8FF00B9663157802767F504754'
+ }
+ TestFrame {
+ time: 2272
+ hash: '624FB09EBE60CB87D767FAF8D2420B1E'
+ }
+ TestFrame {
+ time: 2288
+ hash: 'E5AF0CDC33F3275A25ABB09E9165F310'
+ }
+ TestFrame {
+ time: 2304
+ hash: '02BAFB5A81CA66F7670AC93DE5123860'
+ }
+ TestFrame {
+ time: 2320
+ hash: 'E7AA6374C73832E57CEB2427A1E258AA'
+ }
+ TestFrame {
+ time: 2336
+ hash: 'B5ABD0DFF1AB076FAAC7CC226E83F5D0'
+ }
+ TestFrame {
+ time: 2352
+ hash: 'B759ACC35BCCFF8EFC2E6FE276DDC0F7'
+ }
+ TestFrame {
+ time: 2368
+ hash: 'CE52E18C1F7732768779863B45314FF5'
+ }
+ TestFrame {
+ time: 2384
+ hash: '99D30652559DD6931E0C95543EEAA149'
+ }
+ TestFrame {
+ time: 2400
+ hash: 'FFBD9A00E05E085B89296D19D5CAEC57'
+ }
+ TestFrame {
+ time: 2416
+ hash: '9C9D658B9C25602816B8066BF19105DB'
+ }
+ TestFrame {
+ time: 2432
+ hash: '2B7FD058E6601E22A30BB7106B1C683B'
+ }
+ TestFrame {
+ time: 2448
+ hash: 'F4C7E26B19EE0A3E7C9688685EB7BD05'
+ }
+ TestFrame {
+ time: 2464
+ hash: '0DC6D593BCEFF56B7F81F2A49D37FEFB'
+ }
+ TestFrame {
+ time: 2480
+ hash: '9BFD7AD5091CCBDDE43C593E133A7B10'
+ }
+ TestFrame {
+ time: 2496
+ hash: '2703B617937914A90EA42EBF249D79EE'
+ }
+ TestFrame {
+ time: 2512
+ hash: 'B77E2983138254016C4CCA53100F46FA'
+ }
+ TestFrame {
+ time: 2528
+ hash: '60C4DD24187D1281081479E586F02B37'
+ }
+ TestFrame {
+ time: 2544
+ hash: '62F2511ABD99EF1231C9FA4B91D4ABFE'
+ }
+ TestFrame {
+ time: 2560
+ hash: 'E309B3353FD174E883D309571CADDC98'
+ }
+ TestFrame {
+ time: 2576
+ hash: '1E2D6A134C7B12DDE551B148EF4F088C'
+ }
+ TestFrame {
+ time: 2592
+ hash: 'E5DC5450604A491CC24A0DCF5C278B58'
+ }
+ TestFrame {
+ time: 2608
+ hash: 'C8DAE97C10E1962C1E6A51AB3AB8579E'
+ }
+ TestFrame {
+ time: 2624
+ hash: '4E1B7E06F55FB084080689B474F1FE1D'
+ }
+ TestFrame {
+ time: 2640
+ hash: 'B4639C907FA937BF15FAC62421170CD8'
+ }
+ TestFrame {
+ time: 2656
+ hash: 'C250208A0CAEB5F6CB4D3AAC3D7D350B'
+ }
+ TestFrame {
+ time: 2672
+ hash: 'A73351EABECF0D71149EFE31F197413E'
+ }
+ TestFrame {
+ time: 2688
+ hash: '479425F1B7AFF79E4DFB7FCA534AF018'
+ }
+ TestFrame {
+ time: 2704
+ hash: '046D0F0040A52D1F26BA9F7C5DE06EF4'
+ }
+ TestFrame {
+ time: 2720
+ hash: '655778BF13C6080903150B0EB43A7EDC'
+ }
+ TestFrame {
+ time: 2736
+ hash: '72DA0BBE81514870655FDD3354ADAC60'
+ }
+ TestFrame {
+ time: 2752
+ hash: 'DEFE0BDF675C65FFF55AAACED1E4DAE7'
+ }
+ TestFrame {
+ time: 2768
+ hash: 'C988628B6C3D3780E9A865C7694926CD'
+ }
+ TestFrame {
+ time: 2784
+ hash: '5AB17563655231089EDD986FF13D6012'
+ }
+ TestFrame {
+ time: 2800
+ hash: 'C1ADFF1D2E5800ED466D1691D3B17382'
+ }
+ TestFrame {
+ time: 2816
+ hash: '70129BA01FBB19592B9DC0D0A3B3E7DF'
+ }
+ TestFrame {
+ time: 2832
+ hash: '0000829EF7ED908BF430D42904D59CC2'
+ }
+ TestFrame {
+ time: 2848
+ hash: '843D2927F50AB87B4A86B7A6AAEED91F'
+ }
+ TestFrame {
+ time: 2864
+ hash: 'DA86D21756025E7DE8050586D5E2A1F8'
+ }
+ TestFrame {
+ time: 2880
+ hash: '48DD1BD6580133B0793FEE327EA4F1E6'
+ }
+ TestFrame {
+ time: 2896
+ hash: 'F0618193DCD0BA2837249515A1898B1C'
+ }
+ TestFrame {
+ time: 2912
+ hash: 'A530184E57251065286C0CBBA7301E9C'
+ }
+ TestFrame {
+ time: 2928
+ hash: '64A1D7203973D65DD342793007A61C58'
+ }
+ TestFrame {
+ time: 2944
+ hash: '5B830DFC6BA442772DE87D75D5A578DE'
+ }
+ TestFrame {
+ time: 2960
+ hash: '5563B056B0409B65F60DD16DD0DD890E'
+ }
+ TestFrame {
+ time: 2976
+ hash: 'B8BCF9AD2CA8720C11563A23D8280804'
+ }
+ TestFrame {
+ time: 2992
+ hash: '8C0FCDA4F8956394C53FC4BA18CAA850'
+ }
+}
diff --git a/tests/auto/declarative/visual/colorAnimation/data/raster/manifest.xml b/tests/auto/declarative/visual/colorAnimation/data/raster/manifest.xml
new file mode 100644
index 0000000..1fe2f15
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/data/raster/manifest.xml
@@ -0,0 +1,522 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+ TestFrame {
+ time: 16
+ hash: 'E5BDA0DAF98288CE18DB6CE06EDA3BA0'
+ }
+ TestFrame {
+ time: 32
+ hash: 'D35008F75B8C992F80FB16BA7203649D'
+ }
+ TestFrame {
+ time: 48
+ hash: '14F43E0784DDF42EA8550DB88C501BF1'
+ }
+ TestFrame {
+ time: 64
+ hash: '02276E158B5391480B1BDEAADF1FB903'
+ }
+ TestFrame {
+ time: 80
+ hash: '35D9513EB97A2C482B7CD197DE910934'
+ }
+ TestFrame {
+ time: 96
+ hash: 'FAF0FD681E60BB2489099F5DF772B6CD'
+ }
+ TestFrame {
+ time: 112
+ hash: 'A863D3E346F94785A3A392FDC91526EB'
+ }
+ TestFrame {
+ time: 128
+ hash: 'FDF328D3F6EB8410DA59A91345E41A44'
+ }
+ TestFrame {
+ time: 144
+ hash: '83514A3B10D5BE8F6C3B128D0F3E0B1C'
+ }
+ TestFrame {
+ time: 160
+ hash: 'EAD0EAE76CD00189075964671EFFBAEA'
+ }
+ TestFrame {
+ time: 176
+ hash: '24D2457FCD51490FDA23071BF9929D12'
+ }
+ TestFrame {
+ time: 192
+ hash: '1478683446CF543DACBE31D0B76A98A6'
+ }
+ TestFrame {
+ time: 208
+ hash: '99F7DA1F31FE920F6C02ADD4042AE925'
+ }
+ TestFrame {
+ time: 224
+ hash: '22DEF892006CF66667770B0F17BAF6C0'
+ }
+ TestFrame {
+ time: 240
+ hash: '6A36D5A77099BFD58BAF285478FF04E4'
+ }
+ TestFrame {
+ time: 256
+ hash: '6258150666B59B20AB476724C07FC20C'
+ }
+ TestFrame {
+ time: 272
+ hash: 'F1636315BC950A6DD400D9C7ED263B88'
+ }
+ TestFrame {
+ time: 288
+ hash: '18447EA8DC2E8DA956788E5B3CF3790A'
+ }
+ TestFrame {
+ time: 304
+ hash: '1D2A6E65997A73E9E670356C8E8B63B2'
+ }
+ TestFrame {
+ time: 320
+ hash: 'BED0242C0F9EF229D1392835286D5782'
+ }
+ TestFrame {
+ time: 336
+ hash: '88923C190E9E5BEADEF8A409C06DF9D6'
+ }
+ TestFrame {
+ time: 352
+ hash: '2D133E7EE60C97386F57838B3F0976C7'
+ }
+ TestFrame {
+ time: 368
+ hash: '85B1821CC50F2A9F3ED6944F792B7A2F'
+ }
+ TestFrame {
+ time: 384
+ hash: '395195716D76BC0BE7B2033ED37A7A1C'
+ }
+ TestFrame {
+ time: 400
+ hash: '243DBFFCF416926242BBCB7348974C4C'
+ }
+ TestFrame {
+ time: 416
+ hash: 'A755068679616D8AC65C2AA7431F2A19'
+ }
+ TestFrame {
+ time: 432
+ hash: 'E8249B35A47EB492CBDF2D91CC8426F0'
+ }
+ TestFrame {
+ time: 448
+ hash: '15F3DA1C0E6F0779B96859D51171DD27'
+ }
+ TestFrame {
+ time: 464
+ hash: '258C0C756AAC3DE743B43051F2AACE6B'
+ }
+ TestFrame {
+ time: 480
+ hash: 'A58B9FDF301D72B2CC5C93934CC8927B'
+ }
+ TestFrame {
+ time: 496
+ hash: 'A9181D30870D472521F8904818CE520F'
+ }
+ TestFrame {
+ time: 512
+ hash: '7F9E94069CCF3897C26A71BD7BECD903'
+ }
+ TestFrame {
+ time: 528
+ hash: 'BDF305C2F46CDB86DBF57B1E0CC5A65B'
+ }
+ TestFrame {
+ time: 544
+ hash: 'FE5B6865D7E4FC7D1D42C1E74F8666F7'
+ }
+ TestFrame {
+ time: 560
+ hash: '734F0DE45A6E34C9EAB7EF606196F96A'
+ }
+ TestFrame {
+ time: 576
+ hash: '02A361C4534FDF7F286DC3E6DC23275C'
+ }
+ TestFrame {
+ time: 592
+ hash: 'E649155AD69999C14B92F6561E4D1185'
+ }
+ TestFrame {
+ time: 608
+ hash: '01AF177084FAB755D622973F64B92018'
+ }
+ TestFrame {
+ time: 624
+ hash: '097CC4A082DFAB995D213A3A73883C97'
+ }
+ TestFrame {
+ time: 640
+ hash: 'D7B4239A3280B1EB8E885E3F422DF8E9'
+ }
+ TestFrame {
+ time: 656
+ hash: '59893977994E34E83F91E7CE3AD65D6D'
+ }
+ TestFrame {
+ time: 672
+ hash: 'B68E3FBB5CDCD6BD96DF7DEC558DB42B'
+ }
+ TestFrame {
+ time: 688
+ hash: '94AD0580648F36A1E18A9EA7E249B04D'
+ }
+ TestFrame {
+ time: 704
+ hash: '750A4C01D2F5806A89A1C6CC6A9B9A68'
+ }
+ TestFrame {
+ time: 720
+ hash: '4F109F50F388F1BFA4BC6B03B3E6E514'
+ }
+ TestFrame {
+ time: 736
+ hash: 'C6168D5CF27A533E8EE636637667BE47'
+ }
+ TestFrame {
+ time: 752
+ hash: 'F8120547BED987AA34C00DA5A01A4D1E'
+ }
+ TestFrame {
+ time: 768
+ hash: 'CBFF526136FA2C128C8B898FBBEF9E5C'
+ }
+ TestFrame {
+ time: 784
+ hash: 'F29E52398FAB1A239A63DF4C32F2FC69'
+ }
+ TestFrame {
+ time: 800
+ hash: '7178BFE86FD2FD513218B33760460F8D'
+ }
+ TestFrame {
+ time: 816
+ hash: 'CA83285BC8AC633403896FE976896EB0'
+ }
+ TestFrame {
+ time: 832
+ hash: '96BA486C09CC69D5AA38C46C00DF1181'
+ }
+ TestFrame {
+ time: 848
+ hash: 'B88EAB335842787869F4A14824C19DD8'
+ }
+ TestFrame {
+ time: 864
+ hash: '065AA59012729E1E1A246A2083142690'
+ }
+ TestFrame {
+ time: 880
+ hash: 'DD0E98C8398861002C5F178C5F9F612D'
+ }
+ TestFrame {
+ time: 896
+ hash: '04192C2B545948048ECCF4D81BBDE198'
+ }
+ TestMouse {
+ time: 912
+ type: 2
+ button: 1
+ buttons: 1
+ globalPos: '1739,207'
+ pos: '75,95'
+ }
+ TestFrame {
+ time: 912
+ hash: 'BB7502C7208281EF9FD41714AB88A1A8'
+ }
+ TestFrame {
+ time: 928
+ hash: '5397195471890D08B703DCA101E5BC7C'
+ }
+ TestFrame {
+ time: 944
+ hash: '4C678CDBEBB2FFD2CBF012CA77800CDE'
+ }
+ TestFrame {
+ time: 960
+ hash: '0D7A34ECD0C7F52B2C015037BF1902C6'
+ }
+ TestMouse {
+ time: 976
+ type: 3
+ button: 1
+ buttons: 0
+ globalPos: '1739,207'
+ pos: '75,95'
+ }
+ TestFrame {
+ time: 976
+ hash: 'FD9D5048BE749AC4369FDA2D018B43AE'
+ }
+ TestFrame {
+ time: 992
+ hash: '93EE03795CD57AE6F7FE3A020B039AD4'
+ }
+ TestFrame {
+ time: 1008
+ hash: '5E1118963F219C39761CA7FBF564A9CA'
+ }
+ TestFrame {
+ time: 1024
+ hash: '8F40038741903150136170503649D941'
+ }
+ TestFrame {
+ time: 1040
+ hash: 'B087B7D0AA6224821F8E18718FF5E77D'
+ }
+ TestFrame {
+ time: 1056
+ hash: 'AA46B04A3C67DC772265ED2901955565'
+ }
+ TestFrame {
+ time: 1072
+ hash: 'AC024BF2AEB4BECDF31A09FE0A6DB8F3'
+ }
+ TestFrame {
+ time: 1088
+ hash: '13745A174E4D06E2108A5BF125BA50CC'
+ }
+ TestFrame {
+ time: 1104
+ hash: 'BD972F0D8E230ECA0B3FEA1B8C960C08'
+ }
+ TestFrame {
+ time: 1120
+ hash: 'CBDBEC802A58E7CED0CF45B3AB0BC0BA'
+ }
+ TestFrame {
+ time: 1136
+ hash: '5128584C50305C7D218B81B8367FA3D5'
+ }
+ TestFrame {
+ time: 1152
+ hash: 'A71461D3593F3685620668916DE870BD'
+ }
+ TestFrame {
+ time: 1168
+ hash: '74EBAC8F32CF044B58D9883DBCD9A722'
+ }
+ TestFrame {
+ time: 1184
+ hash: 'FEDC5B638F339B90FE59B478721E65B7'
+ }
+ TestFrame {
+ time: 1200
+ hash: 'BCB8C7159F54C353551DD3BFF3203966'
+ }
+ TestFrame {
+ time: 1216
+ hash: '4E9B083075BC5E9287A8ABC982778B56'
+ }
+ TestFrame {
+ time: 1232
+ hash: '1D6F02AA99AFA47D77FC49AB894B365A'
+ }
+ TestFrame {
+ time: 1248
+ hash: 'A204FEEC783B3B05DE4C209C21745826'
+ }
+ TestFrame {
+ time: 1264
+ hash: '665A2A8FF00B9663157802767F504754'
+ }
+ TestFrame {
+ time: 1280
+ hash: '624FB09EBE60CB87D767FAF8D2420B1E'
+ }
+ TestFrame {
+ time: 1296
+ hash: 'E5AF0CDC33F3275A25ABB09E9165F310'
+ }
+ TestFrame {
+ time: 1312
+ hash: '02BAFB5A81CA66F7670AC93DE5123860'
+ }
+ TestFrame {
+ time: 1328
+ hash: 'E7AA6374C73832E57CEB2427A1E258AA'
+ }
+ TestFrame {
+ time: 1344
+ hash: 'B5ABD0DFF1AB076FAAC7CC226E83F5D0'
+ }
+ TestFrame {
+ time: 1360
+ hash: 'B759ACC35BCCFF8EFC2E6FE276DDC0F7'
+ }
+ TestFrame {
+ time: 1376
+ hash: 'CE52E18C1F7732768779863B45314FF5'
+ }
+ TestFrame {
+ time: 1392
+ hash: '99D30652559DD6931E0C95543EEAA149'
+ }
+ TestFrame {
+ time: 1408
+ hash: 'FFBD9A00E05E085B89296D19D5CAEC57'
+ }
+ TestFrame {
+ time: 1424
+ hash: '9C9D658B9C25602816B8066BF19105DB'
+ }
+ TestFrame {
+ time: 1440
+ hash: '2B7FD058E6601E22A30BB7106B1C683B'
+ }
+ TestFrame {
+ time: 1456
+ hash: 'F4C7E26B19EE0A3E7C9688685EB7BD05'
+ }
+ TestFrame {
+ time: 1472
+ hash: '0DC6D593BCEFF56B7F81F2A49D37FEFB'
+ }
+ TestFrame {
+ time: 1488
+ hash: '9BFD7AD5091CCBDDE43C593E133A7B10'
+ }
+ TestFrame {
+ time: 1504
+ hash: '2703B617937914A90EA42EBF249D79EE'
+ }
+ TestFrame {
+ time: 1520
+ hash: 'B77E2983138254016C4CCA53100F46FA'
+ }
+ TestFrame {
+ time: 1536
+ hash: '60C4DD24187D1281081479E586F02B37'
+ }
+ TestFrame {
+ time: 1552
+ hash: '62F2511ABD99EF1231C9FA4B91D4ABFE'
+ }
+ TestFrame {
+ time: 1568
+ hash: 'E309B3353FD174E883D309571CADDC98'
+ }
+ TestFrame {
+ time: 1584
+ hash: '1E2D6A134C7B12DDE551B148EF4F088C'
+ }
+ TestFrame {
+ time: 1600
+ hash: 'E5DC5450604A491CC24A0DCF5C278B58'
+ }
+ TestFrame {
+ time: 1616
+ hash: 'C8DAE97C10E1962C1E6A51AB3AB8579E'
+ }
+ TestFrame {
+ time: 1632
+ hash: '4E1B7E06F55FB084080689B474F1FE1D'
+ }
+ TestFrame {
+ time: 1648
+ hash: 'B4639C907FA937BF15FAC62421170CD8'
+ }
+ TestFrame {
+ time: 1664
+ hash: 'C250208A0CAEB5F6CB4D3AAC3D7D350B'
+ }
+ TestFrame {
+ time: 1680
+ hash: 'A73351EABECF0D71149EFE31F197413E'
+ }
+ TestFrame {
+ time: 1696
+ hash: '479425F1B7AFF79E4DFB7FCA534AF018'
+ }
+ TestFrame {
+ time: 1712
+ hash: '046D0F0040A52D1F26BA9F7C5DE06EF4'
+ }
+ TestFrame {
+ time: 1728
+ hash: '655778BF13C6080903150B0EB43A7EDC'
+ }
+ TestFrame {
+ time: 1744
+ hash: '72DA0BBE81514870655FDD3354ADAC60'
+ }
+ TestFrame {
+ time: 1760
+ hash: 'DEFE0BDF675C65FFF55AAACED1E4DAE7'
+ }
+ TestFrame {
+ time: 1776
+ hash: 'C988628B6C3D3780E9A865C7694926CD'
+ }
+ TestFrame {
+ time: 1792
+ hash: '5AB17563655231089EDD986FF13D6012'
+ }
+ TestFrame {
+ time: 1808
+ hash: 'C1ADFF1D2E5800ED466D1691D3B17382'
+ }
+ TestFrame {
+ time: 1824
+ hash: '70129BA01FBB19592B9DC0D0A3B3E7DF'
+ }
+ TestFrame {
+ time: 1840
+ hash: '0000829EF7ED908BF430D42904D59CC2'
+ }
+ TestFrame {
+ time: 1856
+ hash: '843D2927F50AB87B4A86B7A6AAEED91F'
+ }
+ TestFrame {
+ time: 1872
+ hash: 'DA86D21756025E7DE8050586D5E2A1F8'
+ }
+ TestFrame {
+ time: 1888
+ hash: '48DD1BD6580133B0793FEE327EA4F1E6'
+ }
+ TestFrame {
+ time: 1904
+ hash: 'F0618193DCD0BA2837249515A1898B1C'
+ }
+ TestFrame {
+ time: 1920
+ hash: 'A530184E57251065286C0CBBA7301E9C'
+ }
+ TestFrame {
+ time: 1936
+ hash: '64A1D7203973D65DD342793007A61C58'
+ }
+ TestFrame {
+ time: 1952
+ hash: '5B830DFC6BA442772DE87D75D5A578DE'
+ }
+ TestFrame {
+ time: 1968
+ hash: '5563B056B0409B65F60DD16DD0DD890E'
+ }
+ TestFrame {
+ time: 1984
+ hash: 'B8BCF9AD2CA8720C11563A23D8280804'
+ }
+ TestFrame {
+ time: 2000
+ hash: '8C0FCDA4F8956394C53FC4BA18CAA850'
+ }
+}
diff --git a/tests/auto/declarative/visual/colorAnimation/manifest-play.xml b/tests/auto/declarative/visual/colorAnimation/manifest-play.xml
new file mode 100644
index 0000000..8e3de2e
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/manifest-play.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="480" type="2" button="1" buttons="1" globalPos="93,129" pos="89,102"/>
+ <TestMouse time="570" type="3" button="1" buttons="0" globalPos="93,129" pos="89,102"/>
+ <TestFrame time="630" hash="D42762ECD293C6922C5F9593126DE636"/>
+ <TestFrame time="660" hash="8962505FCCB2E7559A99A8EDD325A82B"/>
+ <TestFrame time="690" hash="6812EFDA80607D4FA05CD3A5077F8EF7"/>
+ <TestFrame time="720" hash="A116DF73809679C1C5F9261F49B989F0"/>
+ <TestFrame time="750" hash="DC1B9D40AEE306171AD6625DDCA4EB45"/>
+ <TestFrame time="780" hash="B2DAF0E4C32080229664A8B0A155DE3B"/>
+ <TestFrame time="810" hash="496677B0D8707B91566D1244C46D50DB"/>
+ <TestFrame time="840" hash="A6558D8B0D1FB1D11BEBE36C078386CE"/>
+ <TestFrame time="870" hash="601436BB436D391B0BD5FCC289666208"/>
+ <TestFrame time="900" hash="8CF3CF9EAD875497870CC7C1035802DC"/>
+ <TestFrame time="930" hash="FF6BA6BAC30DADD3DBBFD96F127EB1FE"/>
+ <TestFrame time="960" hash="1D97A2A6890078DCF4CE9E508E5F9F08"/>
+ <TestFrame time="990" hash="58C9116FDDD03DD036820EFCD0DCD392"/>
+ <TestFrame time="1020" hash="E51287B911C140B41D350FCB2091AB80"/>
+ <TestFrame time="1050" hash="7B107411B436FABE469A069E6E5B0C3C"/>
+ <TestFrame time="1080" hash="9D1CB0E58F2BD00DDA0FB463F6BFF526"/>
+ <TestFrame time="1110" hash="35AB7788489B79E5A5C6F2BE11AFC9E1"/>
+ <TestFrame time="1140" hash="C82177AC4A7A497469292C5F0F8C4913"/>
+ <TestFrame time="1170" hash="18763D1B911FDC524DB9E7B2569FE984"/>
+ <TestFrame time="1200" hash="27F63572AAEF6D835272D5D65FCF608B"/>
+ <TestFrame time="1230" hash="585727CAEC1F83ADB9E422BAF058A622"/>
+ <TestFrame time="1260" hash="2C3BBFEFBE6E5FDA1905E9F50985E1B4"/>
+ <TestFrame time="1290" hash="81675C4ABB2696D960BC5F204F05F16B"/>
+ <TestFrame time="1320" hash="6D0F3CCC06EF1E3A895ECC9A8DE90039"/>
+ <TestFrame time="1350" hash="0BF36093CCAEA8BDAE96D4939A8DDE20"/>
+ <TestFrame time="1380" hash="5A1CBC68AB59977B65492B0F8A664418"/>
+ <TestFrame time="1410" hash="C35831A8C59D56193CED2C4AADB4DFCE"/>
+ <TestFrame time="1440" hash="ED15973425A8B8528896B344A61393AA"/>
+ <TestFrame time="1470" hash="EA8FC02A8606680C089F0C0CE454ABE3"/>
+ <TestFrame time="1500" hash="CFB5CFBA0A0BC62C0D03908FB9599A8E"/>
+ <TestFrame time="1530" hash="09FAA04AFB50B48BD6A83F9E25F9DDDB"/>
+ <TestFrame time="1560" hash="0FDD0B8CDCCEB78C7C67AB0F5EA74D6A"/>
+ <TestFrame time="1590" hash="058D26146879900B5E5CCE05AE38BA0E"/>
+ <TestFrame time="1620" hash="80F9074C50F967C99D4C3A3FF9EC3E71"/>
+ <TestFrame time="1650" hash="AD9BDCEEC1C058D6B658C5BA0D0BC1F0"/>
+ <TestFrame time="1680" hash="AC14DF5458F91001181154F8C68BCE2B"/>
+ <TestFrame time="1710" hash="AE9225263E4C8E75E4D0F1D7192B4260"/>
+ <TestFrame time="1740" hash="D3D50F1B7F476E79E5B99E0E6D4CF827"/>
+ <TestFrame time="1770" hash="A1367445C5232ACCBF4904A415416EA4"/>
+ <TestFrame time="1800" hash="A21C0F1DA9B64A5B000558BA1F2E495D"/>
+ <TestFrame time="1830" hash="61AF477B6FB22E38E698375EA5793D22"/>
+ <TestFrame time="1860" hash="B3AD3501D527939CEAA4F124AB10B2DF"/>
+ <TestFrame time="1890" hash="0C2BF65A43AE87AFB0068F9FA4A74707"/>
+ <TestFrame time="1920" hash="5B7F96C797BEE4FD1B04538DE5549C1B"/>
+ <TestFrame time="1950" hash="4C861E936A3F1AFE323395E30174F8CC"/>
+ <TestFrame time="1980" hash="87F1966E5B0E924EB7CEED5520D120BF"/>
+ <TestFrame time="2010" hash="1980755E0D80469D4DC0B9B0309F2DEB"/>
+ <TestFrame time="2040" hash="38A7ACC2E5607FC0965B7B376A0D3524"/>
+ <TestFrame time="2070" hash="4434746833EFF5A3A76491024763990A"/>
+ <TestFrame time="2100" hash="A8BAD928F92E851B45723068B7FEF739"/>
+ <TestFrame time="2130" hash="A96F5C522C0ECA5C78E982E4235218CB"/>
+ <TestFrame time="2160" hash="135F0EFEDE2832B76F49966EBD629879"/>
+ <TestFrame time="2190" hash="A51C6E443413F184CAAE8A7F98A369C8"/>
+ <TestFrame time="2220" hash="62A7521EE62E6A2543B3141C1EFCE72A"/>
+ <TestFrame time="2250" hash="D416A41125659167B3E6AD68F66F6E64"/>
+ <TestFrame time="2280" hash="0F653B5E965665A43F50437724DC704C"/>
+ <TestFrame time="2310" hash="13A6E2485179501FF3AA8BA91A5050B4"/>
+ <TestFrame time="2340" hash="9423475D3832FBABEC56B80FA9161020"/>
+ <TestFrame time="2370" hash="497B21108A6CB127DB066B32D06D992A"/>
+ <TestFrame time="2400" hash="22F01CB9B4F8FF01410566A61E281373"/>
+ <TestFrame time="2430" hash="A099640BC088E14E20585CB87FC5C6F1"/>
+ <TestFrame time="2460" hash="AC2954553C333EA1D524CE51CD35958A"/>
+ <TestFrame time="2490" hash="771E882CC788BECAA82E71E6FBAB150D"/>
+ <TestFrame time="2520" hash="42CEDA45D88A8D2B3DA5B749F4C3C1BF"/>
+ <TestFrame time="2550" hash="C6E1F91B917E47246E012D1B203E0DC2"/>
+ <TestFrame time="2580" hash="EFB3E57CF265B6E36AA4DF72771D119C"/>
+ <TestFrame time="2610" hash="657FC7FD496E5A2FC84F63930E0D1DE3"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/easing/easing.qml b/tests/auto/declarative/visual/easing/easing.qml
new file mode 100644
index 0000000..4a0ed14
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/easing.qml
@@ -0,0 +1,186 @@
+Rect {
+ id: item
+ width: 600
+ height: layout.height
+ color: "white"
+ resources: [
+ ListModel {
+ id: easingtypes
+ ListElement {
+ type: "easeNone"
+ }
+ ListElement {
+ type: "easeInQuad"
+ }
+ ListElement {
+ type: "easeOutQuad"
+ }
+ ListElement {
+ type: "easeInOutQuad"
+ }
+ ListElement {
+ type: "easeOutInQuad"
+ }
+ ListElement {
+ type: "easeInCubic"
+ }
+ ListElement {
+ type: "easeOutCubic"
+ }
+ ListElement {
+ type: "easeInOutCubic"
+ }
+ ListElement {
+ type: "easeOutInCubic"
+ }
+ ListElement {
+ type: "easeInQuart"
+ }
+ ListElement {
+ type: "easeOutQuart"
+ }
+ ListElement {
+ type: "easeInOutQuart"
+ }
+ ListElement {
+ type: "easeOutInQuart"
+ }
+ ListElement {
+ type: "easeInQuint"
+ }
+ ListElement {
+ type: "easeOutQuint"
+ }
+ ListElement {
+ type: "easeInOutQuint"
+ }
+ ListElement {
+ type: "easeOutInQuint"
+ }
+ ListElement {
+ type: "easeInSine"
+ }
+ ListElement {
+ type: "easeOutSine"
+ }
+ ListElement {
+ type: "easeInOutSine"
+ }
+ ListElement {
+ type: "easeOutInSine"
+ }
+ ListElement {
+ type: "easeInExpo"
+ }
+ ListElement {
+ type: "easeOutExpo"
+ }
+ ListElement {
+ type: "easeInOutExpo"
+ }
+ ListElement {
+ type: "easeOutInExpo"
+ }
+ ListElement {
+ type: "easeInCirc"
+ }
+ ListElement {
+ type: "easeOutCirc"
+ }
+ ListElement {
+ type: "easeInOutCirc"
+ }
+ ListElement {
+ type: "easeOutInCirc"
+ }
+ ListElement {
+ type: "easeInElastic"
+ }
+ ListElement {
+ type: "easeOutElastic"
+ }
+ ListElement {
+ type: "easeInOutElastic"
+ }
+ ListElement {
+ type: "easeOutInElastic"
+ }
+ ListElement {
+ type: "easeInBack"
+ }
+ ListElement {
+ type: "easeOutBack"
+ }
+ ListElement {
+ type: "easeInOutBack"
+ }
+ ListElement {
+ type: "easeOutInBack"
+ }
+ ListElement {
+ type: "easeOutBounce"
+ }
+ ListElement {
+ type: "easeInBounce"
+ }
+ ListElement {
+ type: "easeInOutBounce"
+ }
+ ListElement {
+ type: "easeOutInBounce"
+ }
+ }
+ ]
+ VerticalLayout {
+ id: layout
+ anchors.left: item.left
+ anchors.right: item.right
+ Repeater {
+ dataSource: easingtypes
+ Component {
+ Text {
+ id: text
+ text: type
+ height: 18
+ font.italic: true
+ color: "black"
+ states: [
+ State {
+ name: "from"
+ when: !mouse.pressed
+ SetProperty {
+ target: text
+ property: "x"
+ value: 0
+ }
+ },
+ State {
+ name: "to"
+ when: mouse.pressed
+ SetProperty {
+ target: text
+ property: "x"
+ value: item.width-100
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "to"
+ reversible: true
+ NumericAnimation {
+ properties: "x"
+ easing: type
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ MouseRegion {
+ id: mouse
+ anchors.fill: layout
+ }
+}
diff --git a/tests/auto/declarative/visual/easing/image0.png b/tests/auto/declarative/visual/easing/image0.png
new file mode 100644
index 0000000..dbe03aa
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/easing/manifest-play.xml b/tests/auto/declarative/visual/easing/manifest-play.xml
new file mode 100644
index 0000000..3c84452
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/manifest-play.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="480" type="2" button="1" buttons="1" globalPos="487,444" pos="483,417"/>
+ <TestFrame time="510" hash="83FB660D6CABAAFCB27C6EC001B14110"/>
+ <TestFrame time="540" hash="27FCD68F610024000CA6D3A8D9F0CF09"/>
+ <TestFrame time="570" hash="14728A6160AF51FCA8562D6A020BBA79"/>
+ <TestFrame time="600" hash="BDDB81682B30A6918927ACB59608D14E"/>
+ <TestFrame time="630" hash="03F16A41DCD31E41935E54763757C6D5"/>
+ <TestFrame time="660" hash="2D04EA1EBEDC77CF5D42A1B491A57EA6"/>
+ <TestFrame time="690" hash="762C36B33B75F24427CA45F4AD06B64E"/>
+ <TestFrame time="720" hash="AA02624CC889C95A99BBE58365F4FAAD"/>
+ <TestFrame time="750" hash="0529200188188708A18CE0F931780DBD"/>
+ <TestFrame time="780" hash="56036B63822AF34F26B149069CD189C6"/>
+ <TestFrame time="810" hash="CFFC6583E2BA1E47E1439BED6FE69665"/>
+ <TestFrame time="840" hash="25A1AFDC945D5264FF0337A421143A3C"/>
+ <TestFrame time="870" hash="601FA34B5E15E7B87E6490580C2E1858"/>
+ <TestFrame time="900" hash="1CA085F6CB8509957A51F6182F7F5443"/>
+ <TestFrame time="930" hash="09B5849DF18F6817F7450230DFEC0E95"/>
+ <TestFrame time="960" hash="15D212C1291DF97E3DEA5AA8793AD5CB"/>
+ <TestFrame time="990" hash="D6E42E8F4D06BDDBAE998079AC2C79AD"/>
+ <TestFrame time="1020" hash="7016B5C435006D859AB087A73299B6D5"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/easing/manifest.xml b/tests/auto/declarative/visual/easing/manifest.xml
new file mode 100644
index 0000000..3c84452
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/manifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="480" type="2" button="1" buttons="1" globalPos="487,444" pos="483,417"/>
+ <TestFrame time="510" hash="83FB660D6CABAAFCB27C6EC001B14110"/>
+ <TestFrame time="540" hash="27FCD68F610024000CA6D3A8D9F0CF09"/>
+ <TestFrame time="570" hash="14728A6160AF51FCA8562D6A020BBA79"/>
+ <TestFrame time="600" hash="BDDB81682B30A6918927ACB59608D14E"/>
+ <TestFrame time="630" hash="03F16A41DCD31E41935E54763757C6D5"/>
+ <TestFrame time="660" hash="2D04EA1EBEDC77CF5D42A1B491A57EA6"/>
+ <TestFrame time="690" hash="762C36B33B75F24427CA45F4AD06B64E"/>
+ <TestFrame time="720" hash="AA02624CC889C95A99BBE58365F4FAAD"/>
+ <TestFrame time="750" hash="0529200188188708A18CE0F931780DBD"/>
+ <TestFrame time="780" hash="56036B63822AF34F26B149069CD189C6"/>
+ <TestFrame time="810" hash="CFFC6583E2BA1E47E1439BED6FE69665"/>
+ <TestFrame time="840" hash="25A1AFDC945D5264FF0337A421143A3C"/>
+ <TestFrame time="870" hash="601FA34B5E15E7B87E6490580C2E1858"/>
+ <TestFrame time="900" hash="1CA085F6CB8509957A51F6182F7F5443"/>
+ <TestFrame time="930" hash="09B5849DF18F6817F7450230DFEC0E95"/>
+ <TestFrame time="960" hash="15D212C1291DF97E3DEA5AA8793AD5CB"/>
+ <TestFrame time="990" hash="D6E42E8F4D06BDDBAE998079AC2C79AD"/>
+ <TestFrame time="1020" hash="7016B5C435006D859AB087A73299B6D5"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/easing/pics/qtlogo.png b/tests/auto/declarative/visual/easing/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/pics/qtlogo.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flickable/Day.qml b/tests/auto/declarative/visual/flickable/Day.qml
new file mode 100644
index 0000000..63fbc78
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/Day.qml
@@ -0,0 +1,26 @@
+Rect {
+ property string day
+
+ width: 400
+ height: 500
+ radius: 7
+ pen.color: "black"
+ id: Page
+ Image {
+ x: 10
+ y: 10
+ source: "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"
+ }
+}
diff --git a/tests/auto/declarative/visual/flickable/cork.jpg b/tests/auto/declarative/visual/flickable/cork.jpg
new file mode 100644
index 0000000..d4d706c
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/cork.jpg
Binary files differ
diff --git a/tests/auto/declarative/visual/flickable/flickable.qml b/tests/auto/declarative/visual/flickable/flickable.qml
new file mode 100644
index 0000000..5946c40
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/flickable.qml
@@ -0,0 +1,53 @@
+Rect {
+ color: "lightSteelBlue"
+ width: 800
+ height: 500
+ ListModel {
+ id: List
+ ListElement {
+ name: "Sunday"
+ dayColor: "#808080"
+ }
+ ListElement {
+ name: "Monday"
+ dayColor: "blue"
+ }
+ ListElement {
+ name: "Tuesday"
+ dayColor: "yellow"
+ }
+ ListElement {
+ name: "Wednesday"
+ dayColor: "purple"
+ }
+ ListElement {
+ name: "Thursday"
+ dayColor: "blue"
+ }
+ ListElement {
+ name: "Friday"
+ dayColor: "green"
+ }
+ ListElement {
+ name: "Saturday"
+ dayColor: "orange"
+ }
+ }
+ Flickable {
+ id: Flick
+ anchors.fill: parent
+ viewportWidth: Lay.width
+ HorizontalLayout {
+ id: Lay
+ Repeater {
+ dataSource: List
+ Component {
+ Day {
+ day: name
+ color: dayColor
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/flickable/image0.png b/tests/auto/declarative/visual/flickable/image0.png
new file mode 100644
index 0000000..a70ec71
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flickable/manifest-fail.xml b/tests/auto/declarative/visual/flickable/manifest-fail.xml
new file mode 100644
index 0000000..0701fa1
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/manifest-fail.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="930" type="2" button="1" buttons="1" globalPos="1459,490" pos="712,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1457,490" pos="710,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1454,490" pos="707,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1446,488" pos="699,461"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1438,488" pos="691,461"/>
+ <TestFrame time="1020" hash="3A44CE7B924456B70E9ACAA4D6211036"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1402,484" pos="655,457"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1386,484" pos="639,457"/>
+ <TestFrame time="1050" hash="CC4B8F76C3758329C4792CC2499588B9"/>
+ <TestMouse time="1080" type="5" button="0" buttons="1" globalPos="1328,478" pos="581,451"/>
+ <TestFrame time="1080" hash="A314FC89F9915A0F62E77C649052F30B"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1306,476" pos="559,449"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1258,472" pos="511,445"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1234,468" pos="487,441"/>
+ <TestFrame time="1110" hash="496BEE45FD87ACA4335EB656DAB38E7C"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1206,466" pos="459,439"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1140,460" pos="393,433"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1106,454" pos="359,427"/>
+ <TestFrame time="1140" hash="9052B7F038D1BE19B5C603F2B376D95C"/>
+ <TestMouse time="1170" type="5" button="0" buttons="1" globalPos="980,438" pos="233,411"/>
+ <TestFrame time="1170" hash="75EBD16D2210983178EC267DD5C7E3DC"/>
+ <TestMouse time="1200" type="5" button="0" buttons="1" globalPos="930,432" pos="183,405"/>
+ <TestMouse time="1200" type="3" button="1" buttons="0" globalPos="930,432" pos="183,405"/>
+ <TestFrame time="1200" hash="A016C7981ACC7C26D0CDE0CF7D71E929"/>
+ <TestFrame time="1260" hash="A2EA153F54B2D98DEC895FC72D3279F0"/>
+ <TestFrame time="1290" hash="2702B6D7429FC955B2061C368910309F"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flickable/manifest.xml b/tests/auto/declarative/visual/flickable/manifest.xml
new file mode 100644
index 0000000..84d6890
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/manifest.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="930" type="2" button="1" buttons="1" globalPos="1459,490" pos="712,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1457,490" pos="710,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1454,490" pos="707,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1446,488" pos="699,461"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1438,488" pos="691,461"/>
+ <TestFrame time="1020" hash="3A44CE7B924456B70E9ACAA4D6211036"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1402,484" pos="655,457"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1386,484" pos="639,457"/>
+ <TestFrame time="1050" hash="CC4B8F76C3758329C4792CC2499588B9"/>
+ <TestMouse time="1080" type="5" button="0" buttons="1" globalPos="1328,478" pos="581,451"/>
+ <TestFrame time="1080" hash="A314FC89F9915A0F62E77C649052F30B"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1306,476" pos="559,449"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1258,472" pos="511,445"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1234,468" pos="487,441"/>
+ <TestFrame time="1110" hash="496BEE45FD87ACA4335EB656DAB38E7C"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1206,466" pos="459,439"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1140,460" pos="393,433"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1106,454" pos="359,427"/>
+ <TestFrame time="1140" hash="9052B7F038D1BE19B5C603F2B376D95C"/>
+ <TestMouse time="1170" type="5" button="0" buttons="1" globalPos="980,438" pos="233,411"/>
+ <TestFrame time="1170" hash="75EBD16D2210983178EC267DD5C7E3DC"/>
+ <TestMouse time="1200" type="5" button="0" buttons="1" globalPos="930,432" pos="183,405"/>
+ <TestMouse time="1200" type="3" button="1" buttons="0" globalPos="930,432" pos="183,405"/>
+ <TestFrame time="1200" hash="A016C7981ACC7C26D0CDE0CF7D71E929"/>
+ <TestFrame time="1260" hash="203B3D2224AA0B9CB9DB64C837402047"/>
+ <TestFrame time="1290" hash="E9974E5662F22716C9BC2CF8D1FF12FE"/>
+ <TestFrame time="1320" hash="1218CCCC399AE53D5D99D3E7AFD73A16"/>
+ <TestFrame time="1350" hash="FA5D19578629F56972955E9FE530BE59"/>
+ <TestFrame time="1380" hash="B5B23BBDF1FEB6E6B55AE3909F607D96"/>
+ <TestFrame time="1410" hash="17EDC257AF24F178455CDEE7B9D73A9F"/>
+ <TestFrame time="1440" hash="F62E75656DC8AEF20426535DC25FC9F7"/>
+ <TestFrame time="1470" hash="973D39071B13FBBC700964CA1E4995DA"/>
+ <TestFrame time="1500" hash="391C67A59AC71B498381FC4D3DA1E8BB"/>
+ <TestFrame time="1530" hash="C1D86256E4BE487CB61AB1CC8D277FF2"/>
+ <TestFrame time="1560" hash="D5324FF0B16AA4B532007236222FEEAA"/>
+ <TestFrame time="1590" hash="4B14446DE1B9DE22D3DFF86A7CC46A05"/>
+ <TestFrame time="1620" hash="49E6FF8DEB537ECE9BDF56135FCB8BE3"/>
+ <TestFrame time="1650" hash="25D8D454CD32513F2E711D1B09DF87AF"/>
+ <TestFrame time="1680" hash="AB511F44DD761AC1070733CB81731451"/>
+ <TestFrame time="1710" hash="3441D361DB85B2522C8CCB8C21D95E70"/>
+ <TestFrame time="1740" hash="DB333DF49E6DB519F1F5436F6EEEF18E"/>
+ <TestFrame time="1770" hash="97044C41A8C27B534707352334CB100E"/>
+ <TestFrame time="1800" hash="C9EE4321669BB45A574D2CD3448553FE"/>
+ <TestFrame time="1830" hash="6E1067FB547479F8AC0214B1DE4F1ABD"/>
+ <TestFrame time="1860" hash="9AC3067759043EF1C8138C6E3D3B26D1"/>
+ <TestFrame time="1890" hash="F90BB455E7D0266C631BFD6657AC673F"/>
+ <TestFrame time="1920" hash="064CA0BCE5BCE1E5409F7E95F501843A"/>
+ <TestFrame time="1950" hash="AC5489FE171E537E5AF6EC9F8B5241DA"/>
+ <TestFrame time="1980" hash="BBF5D953DCF7FF64D99BF10E244FACE0"/>
+ <TestFrame time="2010" hash="309FC8E37A3EC93C41BC5E2F8F2962DB"/>
+ <TestFrame time="2040" hash="192B13ADD78B36E54E3D39E998641F82"/>
+ <TestFrame time="2070" hash="10F9D012CD1ECD9C8A872AA28191599E"/>
+ <TestFrame time="2100" hash="E3C9CE476A02915B7EEAA5D16747BD74"/>
+ <TestFrame time="2130" hash="24AD4F88A8BE8E4059517DA5AB9EC3F9"/>
+ <TestFrame time="2160" hash="74CE8AFFE7BAC8380E9EE27E482107E8"/>
+ <TestFrame time="2190" hash="C3377013131C3D1EEFFAEC37C0359E7B"/>
+ <TestFrame time="2220" hash="1850C61F261E6E148E12C9D9508411E4"/>
+ <TestFrame time="2250" hash="30EEAD3AC4C869FEB9A2E2F18BB5F335"/>
+ <TestFrame time="2280" hash="EB0F744274AF8FF27CAFC73053B63C87"/>
+ <TestFrame time="2310" hash="ADF16B9E820CF7F77E17E2383E0BF345"/>
+ <TestFrame time="2340" hash="8623C727CB6605607679B7C973E5CE61"/>
+ <TestFrame time="2370" hash="DE795BC19AD3B24FF091D6EB500C0C9A"/>
+ <TestFrame time="2400" hash="E85F53F766BE13A62272442916217181"/>
+ <TestFrame time="2430" hash="B5B05BF6D74AC22BC0DC5ECF8AFFD571"/>
+ <TestFrame time="2460" hash="C9DB0041AEA560EA3569FA6A37A8E226"/>
+ <TestFrame time="2490" hash="96B6E45404C4CB7C65A7113294679C96"/>
+ <TestFrame time="2520" hash="780599814A9AEEB63B6604F8627966FC"/>
+ <TestFrame time="2550" hash="40D7E36CD63DC9B6F5E0340F8E61DE4F"/>
+ <TestFrame time="2580" hash="127E4A92CC2AF9B6C7B5686ECED260E3"/>
+ <TestFrame time="2610" hash="10FEB4963AAD931587BAC2101367CB92"/>
+ <TestFrame time="2640" hash="2926893CD68516281E47EAD04720E4DB"/>
+ <TestFrame time="2670" hash="23F790EF701E37C3959465BF5298C9C2"/>
+ <TestFrame time="2700" hash="461224D0A6662450BA361FAF90CA3087"/>
+ <TestFrame time="2730" hash="3779C1CC5CD18633C70CE5614C2FCA33"/>
+ <TestFrame time="2760" hash="D93F3000F95110464793C9BAEF58D694"/>
+ <TestFrame time="2790" hash="0BFCCED8AE73FBCAC251442F002D603C"/>
+ <TestFrame time="2820" hash="AC1D13A5508255DCA994CC4685FB0AE3"/>
+ <TestFrame time="2850" hash="A6709853B44AB203FC8806D3F4159639"/>
+ <TestFrame time="2880" hash="171589A0F67D72F1685836F5EFF2DD10"/>
+ <TestFrame time="2910" hash="D4984C2B663CFA0CDE95F9AD5BC9937B"/>
+ <TestFrame time="2940" hash="1BB6D261C9E800004B180FB8EC0B45AD"/>
+ <TestFrame time="2970" hash="46CD4E37C989FACF2B7CD71A16DB495A"/>
+ <TestFrame time="3000" hash="8ED436FF855C96A8CEB795AE175A7C54"/>
+ <TestFrame time="3030" hash="8ED436FF855C96A8CEB795AE175A7C54"/>
+ <TestFrame time="3060" hash="138D8CC351C847F266C63F323BABD7FE"/>
+ <TestFrame time="3090" hash="8D90560CCF5EEB1475F3AA46295E4DD0"/>
+ <TestFrame time="3120" hash="DD893A953B945365B0F9287A79826A6D"/>
+ <TestFrame time="3150" hash="386A768FD485BB66C9DC1465399B58C8"/>
+ <TestFrame time="3180" hash="21340437F1A05C216005157A8E8A9EEF"/>
+ <TestFrame time="3210" hash="6E2DA9DA5964F59715B08FD59D8BC3EF"/>
+ <TestFrame time="3240" hash="DC7108F44E225D70349889D9E3F62E74"/>
+ <TestMouse time="4110" type="2" button="1" buttons="1" globalPos="853,492" pos="106,465"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="854,493" pos="107,466"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="855,493" pos="108,466"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="856,494" pos="109,467"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="857,494" pos="110,467"/>
+ <TestMouse time="4200" type="5" button="0" buttons="1" globalPos="859,494" pos="112,467"/>
+ <TestMouse time="4200" type="5" button="0" buttons="1" globalPos="860,495" pos="113,468"/>
+ <TestMouse time="4200" type="5" button="0" buttons="1" globalPos="862,495" pos="115,468"/>
+ <TestFrame time="4200" hash="3946A595E81E4388AFDDDB2539B21BF3"/>
+ <TestMouse time="4230" type="5" button="0" buttons="1" globalPos="864,495" pos="117,468"/>
+ <TestMouse time="4230" type="5" button="0" buttons="1" globalPos="869,495" pos="122,468"/>
+ <TestMouse time="4230" type="5" button="0" buttons="1" globalPos="872,495" pos="125,468"/>
+ <TestFrame time="4230" hash="D9F7C86886CC5309846694F5DA98A123"/>
+ <TestMouse time="4260" type="5" button="0" buttons="1" globalPos="875,495" pos="128,468"/>
+ <TestMouse time="4260" type="5" button="0" buttons="1" globalPos="892,497" pos="145,470"/>
+ <TestFrame time="4260" hash="0B923428F4EAF40CB032FE8880B10943"/>
+ <TestMouse time="4290" type="5" button="0" buttons="1" globalPos="911,499" pos="164,472"/>
+ <TestMouse time="4290" type="5" button="0" buttons="1" globalPos="919,499" pos="172,472"/>
+ <TestFrame time="4290" hash="F1FCED7910188DBEDC62E289EC98D14A"/>
+ <TestMouse time="4320" type="5" button="0" buttons="1" globalPos="938,499" pos="191,472"/>
+ <TestFrame time="4320" hash="71A01976611816A5D42BBB6BC6DE5336"/>
+ <TestMouse time="4350" type="5" button="0" buttons="1" globalPos="957,501" pos="210,474"/>
+ <TestMouse time="4350" type="5" button="0" buttons="1" globalPos="960,501" pos="213,474"/>
+ <TestFrame time="4350" hash="204D5511DFAA28AF3E499FD5E503592A"/>
+ <TestMouse time="4380" type="5" button="0" buttons="1" globalPos="968,501" pos="221,474"/>
+ <TestMouse time="4380" type="5" button="0" buttons="1" globalPos="986,503" pos="239,476"/>
+ <TestMouse time="4380" type="5" button="0" buttons="1" globalPos="989,503" pos="242,476"/>
+ <TestFrame time="4380" hash="E7F2934FB80FD155AAE4E558B1D31AF9"/>
+ <TestMouse time="4410" type="5" button="0" buttons="1" globalPos="1015,501" pos="268,474"/>
+ <TestMouse time="4410" type="5" button="0" buttons="1" globalPos="1025,499" pos="278,472"/>
+ <TestFrame time="4410" hash="DE795BC19AD3B24FF091D6EB500C0C9A"/>
+ <TestMouse time="4440" type="5" button="0" buttons="1" globalPos="1065,497" pos="318,470"/>
+ <TestFrame time="4440" hash="3A2D5734CCC3E5690EF24D412B5ADE32"/>
+ <TestMouse time="4470" type="5" button="0" buttons="1" globalPos="1083,495" pos="336,468"/>
+ <TestMouse time="4470" type="5" button="0" buttons="1" globalPos="1135,493" pos="388,466"/>
+ <TestMouse time="4470" type="5" button="0" buttons="1" globalPos="1171,489" pos="424,462"/>
+ <TestFrame time="4470" hash="A5F66816E008610C1DA44270F837C9DF"/>
+ <TestMouse time="4500" type="5" button="0" buttons="1" globalPos="1215,489" pos="468,462"/>
+ <TestMouse time="4500" type="5" button="0" buttons="1" globalPos="1319,483" pos="572,456"/>
+ <TestMouse time="4500" type="5" button="0" buttons="1" globalPos="1379,479" pos="632,452"/>
+ <TestFrame time="4500" hash="6AE11928E7948AD5F9CE5EE07B5E7390"/>
+ <TestMouse time="4530" type="5" button="0" buttons="1" globalPos="1441,475" pos="694,448"/>
+ <TestMouse time="4530" type="3" button="1" buttons="0" globalPos="1441,475" pos="694,448"/>
+ <TestFrame time="4530" hash="47B438BC833CFF7984D3E158B54F0EA5"/>
+ <TestFrame time="4590" hash="DA134DD6826A87BC08F3BE59F3D2866D"/>
+ <TestFrame time="4620" hash="D1E87BD1C6264CE83979D34500EEB85B"/>
+ <TestFrame time="4650" hash="37C13A368649152DD1D43BDD17BEEE97"/>
+ <TestFrame time="4680" hash="C461AE2C388F4B06E958C12B543E53C0"/>
+ <TestFrame time="4710" hash="6070DD498E15C27243F09FD8CF8C0D2F"/>
+ <TestFrame time="4740" hash="FB74E95CF41BDA785991BA01369E9320"/>
+ <TestFrame time="4770" hash="F52AE455BBA3BAD36ABB4DB2480549D6"/>
+ <TestFrame time="4800" hash="9BC4E043F6595493ED32BBAAB949CC15"/>
+ <TestFrame time="4830" hash="4C87F70F6A46B2066021A68435BB285D"/>
+ <TestFrame time="4860" hash="282A523039F702F22C5D7F2B00BCA1F4"/>
+ <TestFrame time="4890" hash="D1623E75F20C00F6F357346F57E5C343"/>
+ <TestFrame time="4920" hash="F96CC72E3671C64D87719E5DF8303FA9"/>
+ <TestFrame time="4950" hash="44D4E09F9AB5C20E7A7F1AEF920B3599"/>
+ <TestFrame time="4980" hash="BBAD1BD87E29C1F0834B16DA9C1317A4"/>
+ <TestFrame time="5010" hash="66DF69AD2EA4823E59F6FC296910822F"/>
+ <TestFrame time="5040" hash="A0DCE22CFADFE091C5474C231EAD191E"/>
+ <TestFrame time="5070" hash="AE67DD3CD8B77D001288558E3C67E675"/>
+ <TestFrame time="5100" hash="B028CC11B70C5288436E49DD439F9F46"/>
+ <TestFrame time="5130" hash="2FBEFA9C751317D668A1074E8BCB8B10"/>
+ <TestFrame time="5160" hash="2DB3A59F7CB89B89CD45B86008CC0541"/>
+ <TestFrame time="5190" hash="AFE0FD3CB16F9DDD3E8DAD46656BE099"/>
+ <TestFrame time="5220" hash="90C04F980A0C008D4B919D9A4B663762"/>
+ <TestFrame time="5250" hash="215CB75F6359548B7A4A408E83049A25"/>
+ <TestFrame time="5280" hash="8EC68EA3F6B54415EC9B860B0207351E"/>
+ <TestFrame time="5310" hash="8FC14C2EB103B4FDC5B17E6E0F2386D1"/>
+ <TestFrame time="5340" hash="938DA507656430E1758CB8B5E9D874B1"/>
+ <TestFrame time="5370" hash="30A3166F0169715DA9FECD48DA257625"/>
+ <TestFrame time="5400" hash="0C24CD68AFE9C24380178417FE835494"/>
+ <TestFrame time="5430" hash="C8A18880023CB12BA98EBDFF65875874"/>
+ <TestFrame time="5460" hash="FE3BCA8DC715A19161FCD48C728366A0"/>
+ <TestFrame time="5490" hash="4771F9D8AA2A177A190879EB543FA138"/>
+ <TestFrame time="5520" hash="971D611BC939AB20B998D659DF2235FE"/>
+ <TestFrame time="5550" hash="7AF899892AE28C61B71A5682F9540DB5"/>
+ <TestFrame time="5580" hash="CCF349DCA802D5D68B6C9CB368104EF8"/>
+ <TestFrame time="5610" hash="3DC13F8B693648ABBE8FD6935832BEC7"/>
+ <TestFrame time="5640" hash="ED2AD5E716D69FD1A87133209695E911"/>
+ <TestFrame time="5670" hash="037B45A66950DF70D8BD7BC0E000ECC7"/>
+ <TestFrame time="5700" hash="43B59CF46A829CAFF7D9C0A6D1175581"/>
+ <TestFrame time="5730" hash="6FF016CE82BFD220418C0A9A644F2F81"/>
+ <TestFrame time="5760" hash="96D37AFF283210D59287526798E9376D"/>
+ <TestFrame time="5790" hash="7289570ABB671359AC2F2DF1898748CA"/>
+ <TestFrame time="5820" hash="2B3AF6424765512B8949BBB9BF6571DC"/>
+ <TestFrame time="5850" hash="23054E1F931342B8A6C5F6D30A9FF158"/>
+ <TestFrame time="5880" hash="E3D6EBB07FC90AD2483E95C09CB9E074"/>
+ <TestFrame time="5910" hash="08EE4C4D9F161AB4118EAD4F4AA8D5B3"/>
+ <TestFrame time="5940" hash="96D37AFF283210D59287526798E9376D"/>
+ <TestFrame time="5970" hash="40FB8747AACD078576573CF346E2C418"/>
+ <TestFrame time="6000" hash="4095D9B46D265D28C88DE0D0E02AC840"/>
+ <TestFrame time="6030" hash="E370C2A5451DC73AE4F742D52E3DAD4D"/>
+ <TestFrame time="6060" hash="AC4DC18BEFE0895C1ADF8EE2E3094A09"/>
+ <TestFrame time="6090" hash="AC4DC18BEFE0895C1ADF8EE2E3094A09"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flipable/flipable.xml b/tests/auto/declarative/visual/flipable/flipable.xml
new file mode 100644
index 0000000..d769e55
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/flipable.xml
@@ -0,0 +1,138 @@
+<Rect color="lightsteelblue" height="400" width="500">
+ <VisualModel id="MyVisualModel">
+ <model>
+ <ListModel id="ListModel">
+ <Person>
+ <name>Jessica</name>
+ <picture>face.png</picture>
+ </Person>
+ <Person>
+ <name>John</name>
+ <picture>photo0.png</picture>
+ </Person>
+ <Person>
+ <name>Susan</name>
+ <picture>photo10.png</picture>
+ </Person>
+ <Person>
+ <name>Samantha</name>
+ <picture>photo1.png</picture>
+ </Person>
+ <Person>
+ <name>Mark</name>
+ <picture>photo2.png</picture>
+ </Person>
+ <Person>
+ <name>Sarah</name>
+ <picture>photo3.png</picture>
+ </Person>
+ <Person>
+ <name>Pam</name>
+ <picture>photo4.png</picture>
+ </Person>
+ <Person>
+ <name>April</name>
+ <picture>photo5.png</picture>
+ </Person>
+ <Person>
+ <name>Tarryn</name>
+ <picture>photo6.png</picture>
+ </Person>
+ <Person>
+ <name>Geoff</name>
+ <picture>photo7.png</picture>
+ </Person>
+ <Person>
+ <name>Bill</name>
+ <picture>photo8.png</picture>
+ </Person>
+ <Person>
+ <name>Stuart</name>
+ <picture>photo9.png</picture>
+ </Person>
+ </ListModel>
+ </model>
+ <delegate>
+ <Package>
+ <Flipable id="MeRect" width="100" height="100">
+ <properties>
+ <Property name="r" type="Real" />
+ </properties>
+ <transform>
+ <Perspective angle="90" x="50" y="50" aspect="1" scale="256"/>
+ <Axis xStart="50" xEnd="50" yStart="0" yEnd="1" rotation="{MeRect.r}" />
+ </transform>
+
+ <front>
+ <Rect radius="5" color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </front>
+
+ <back>
+ <Rect radius="5" color="red" width="100" height="100">
+ <Image anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}" file="{picture}" />
+ </Rect>
+ </back>
+ </Flipable>
+
+ <Item Package.name="leftBox" id="LeftBox"
+ width="100" height="100">
+ <Rect opacity="0.1" width="80" height="80" radius="4"
+ color="grey" x="10" y="10">
+ <Text text="{name}" />
+ <MouseRegion anchors.fill="{parent}" onClick="if(MyItem.currentState=='left') MyItem.currentState='right'; else MyItem.currentState='left';" />
+ </Rect>
+ </Item>
+ <Item Package.name="rightBox" id="RightBox"
+ width="100" height="100">
+ <Rect opacity="0.1" width="80" height="80" radius="4"
+ color="grey" x="10" y="10">
+ <Text text="{name}" />
+ <MouseRegion anchors.fill="{parent}" onClick="if(MyItem.currentState=='left') MyItem.currentState='right'; else MyItem.currentState='left';" />
+ </Rect>
+ </Item>
+ <Item id="MyItem">
+ <states>
+ <State name="left">
+ <SetProperty target="{MeRect}" property="moveToParent" value="{LeftBox}" />
+ </State>
+ <State name="right">
+ <SetProperty target="{MeRect}" property="moveToParent" value="{RightBox}" />
+ <SetProperty target="{MeRect}" property="r" value="180" />
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="*">
+ <NumericAnimation property="r" duration="500" />
+ <SerialAnimation>
+ <SetPropertyAction target="{MeRect}" property="moveToParent" value="{Bounce}" />
+ <ParallelAnimation>
+ <NumericAnimation target="{MeRect}" properties="x" to="0" duration="250" />
+ <NumericAnimation target="{MeRect}" properties="y" to="0" easing="easeInQuad" duration="250"/>
+ </ParallelAnimation>
+ <SetPropertyAction target="{MeRect}" property="moveToParent" />
+ <ParallelAnimation>
+ <NumericAnimation target="{MeRect}" properties="x" to="0" duration="250"/>
+ <NumericAnimation target="{MeRect}" properties="y" to="0" easing="easeOutQuad" duration="250"/>
+ </ParallelAnimation>
+ </SerialAnimation>
+ </Transition>
+ </transitions>
+ <currentState>left</currentState>
+ </Item>
+
+ </Package>
+ </delegate>
+ </VisualModel>
+
+ <Item width="800" height="400" clip="true">
+ <Item z="100" id="Bounce" x="200" y="300" />
+ <ListView id="MyListView" width="400" height="400" x="400"
+ model="{MyVisualModel.parts.rightBox}" />
+
+ <ListView id="MyListView2" width="400" height="400"
+ model="{MyVisualModel.parts.leftBox}" />
+ </Item>
+
+</Rect>
diff --git a/tests/auto/declarative/visual/flipable/image0.png b/tests/auto/declarative/visual/flipable/image0.png
new file mode 100644
index 0000000..affb8a5
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/manifest-play.xml b/tests/auto/declarative/visual/flipable/manifest-play.xml
new file mode 100644
index 0000000..81c08e4
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/manifest-play.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="2040" type="2" button="1" buttons="1" globalPos="812,72" pos="65,45"/>
+ <TestMouse time="2100" type="3" button="1" buttons="0" globalPos="812,72" pos="65,45"/>
+ <TestFrame time="2130" hash="210454ECF70EEA9CA43DD391BC23178B"/>
+ <TestFrame time="2160" hash="F6612DAD879208F4AF100337271C445C"/>
+ <TestFrame time="2190" hash="C77FC41100D0B066F8F0BF4ABCF2F0BF"/>
+ <TestFrame time="2220" hash="1AB3A42E6FC271E049E6071A88AB8EE4"/>
+ <TestFrame time="2250" hash="DB3D5BC6882699DCC0208E4F5294B609"/>
+ <TestFrame time="2280" hash="DC5A8B44283DA4A81D3994B873FC5695"/>
+ <TestFrame time="2310" hash="5149027ECF7813BA64D3AB8FFE0265F5"/>
+ <TestFrame time="2340" hash="B7E801DF476C012AC3E9E48A9D4AA321"/>
+ <TestFrame time="2370" hash="F31A647A6A3EC86D7F16EB3147E5FC29"/>
+ <TestFrame time="2400" hash="FBB068C39D5188A175075667B584F1BE"/>
+ <TestFrame time="2430" hash="EC487AB66384A4A3A718D03555EBFD41"/>
+ <TestFrame time="2460" hash="C7AD11EB051B11ACBA38027013215A05"/>
+ <TestFrame time="2490" hash="AA38FD8E97EC394488274127630E7946"/>
+ <TestFrame time="2520" hash="1CA2B617AC966B54FFA1A61914F68A9D"/>
+ <TestFrame time="2550" hash="1726C0BAA930CAF282154F14AC2FD120"/>
+ <TestFrame time="2580" hash="58F8196148C8B64191AF7B897A811CFB"/>
+ <TestFrame time="2610" hash="D56D3FA137AA63A0215611450B40F3E0"/>
+ <TestFrame time="2640" hash="5E1BCDF996B2903D1EAEAC65E17783C2"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flipable/manifest.xml b/tests/auto/declarative/visual/flipable/manifest.xml
new file mode 100644
index 0000000..81c08e4
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/manifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="2040" type="2" button="1" buttons="1" globalPos="812,72" pos="65,45"/>
+ <TestMouse time="2100" type="3" button="1" buttons="0" globalPos="812,72" pos="65,45"/>
+ <TestFrame time="2130" hash="210454ECF70EEA9CA43DD391BC23178B"/>
+ <TestFrame time="2160" hash="F6612DAD879208F4AF100337271C445C"/>
+ <TestFrame time="2190" hash="C77FC41100D0B066F8F0BF4ABCF2F0BF"/>
+ <TestFrame time="2220" hash="1AB3A42E6FC271E049E6071A88AB8EE4"/>
+ <TestFrame time="2250" hash="DB3D5BC6882699DCC0208E4F5294B609"/>
+ <TestFrame time="2280" hash="DC5A8B44283DA4A81D3994B873FC5695"/>
+ <TestFrame time="2310" hash="5149027ECF7813BA64D3AB8FFE0265F5"/>
+ <TestFrame time="2340" hash="B7E801DF476C012AC3E9E48A9D4AA321"/>
+ <TestFrame time="2370" hash="F31A647A6A3EC86D7F16EB3147E5FC29"/>
+ <TestFrame time="2400" hash="FBB068C39D5188A175075667B584F1BE"/>
+ <TestFrame time="2430" hash="EC487AB66384A4A3A718D03555EBFD41"/>
+ <TestFrame time="2460" hash="C7AD11EB051B11ACBA38027013215A05"/>
+ <TestFrame time="2490" hash="AA38FD8E97EC394488274127630E7946"/>
+ <TestFrame time="2520" hash="1CA2B617AC966B54FFA1A61914F68A9D"/>
+ <TestFrame time="2550" hash="1726C0BAA930CAF282154F14AC2FD120"/>
+ <TestFrame time="2580" hash="58F8196148C8B64191AF7B897A811CFB"/>
+ <TestFrame time="2610" hash="D56D3FA137AA63A0215611450B40F3E0"/>
+ <TestFrame time="2640" hash="5E1BCDF996B2903D1EAEAC65E17783C2"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flipable/pics/arrow.png b/tests/auto/declarative/visual/flipable/pics/arrow.png
new file mode 100644
index 0000000..997190d
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/arrow.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/face.png b/tests/auto/declarative/visual/flipable/pics/face.png
new file mode 100644
index 0000000..e9529ac
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/face.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo0.png b/tests/auto/declarative/visual/flipable/pics/photo0.png
new file mode 100644
index 0000000..26bbf5b
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo1.png b/tests/auto/declarative/visual/flipable/pics/photo1.png
new file mode 100644
index 0000000..2230f71
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo10.png b/tests/auto/declarative/visual/flipable/pics/photo10.png
new file mode 100644
index 0000000..119f142
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo10.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo2.png b/tests/auto/declarative/visual/flipable/pics/photo2.png
new file mode 100644
index 0000000..e3d58c1
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo3.png b/tests/auto/declarative/visual/flipable/pics/photo3.png
new file mode 100644
index 0000000..4b58df4
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo4.png b/tests/auto/declarative/visual/flipable/pics/photo4.png
new file mode 100644
index 0000000..4ed4bd2
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo5.png b/tests/auto/declarative/visual/flipable/pics/photo5.png
new file mode 100644
index 0000000..eb26704
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo6.png b/tests/auto/declarative/visual/flipable/pics/photo6.png
new file mode 100644
index 0000000..69875ce
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo7.png b/tests/auto/declarative/visual/flipable/pics/photo7.png
new file mode 100644
index 0000000..0b117c9
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo8.png b/tests/auto/declarative/visual/flipable/pics/photo8.png
new file mode 100644
index 0000000..b77b997
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo9.png b/tests/auto/declarative/visual/flipable/pics/photo9.png
new file mode 100644
index 0000000..8a974d6
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo9.png
Binary files differ
diff --git a/tests/auto/declarative/visual/pauseAnimation/data/raster/image0.png b/tests/auto/declarative/visual/pauseAnimation/data/raster/image0.png
new file mode 100644
index 0000000..8082422
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/pauseAnimation/data/raster/manifest.qml b/tests/auto/declarative/visual/pauseAnimation/data/raster/manifest.qml
new file mode 100644
index 0000000..de3f32e
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/data/raster/manifest.qml
@@ -0,0 +1,1262 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+ TestFrame {
+ time: 16
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 32
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 48
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 64
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 80
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 96
+ hash: '336D31586171F22D541B989D24B95CBB'
+ }
+ TestFrame {
+ time: 112
+ hash: '6D63FB5C8A80F0280E88B2CDF8641BB9'
+ }
+ TestFrame {
+ time: 128
+ hash: 'EF8941674CB61F54853DC33652BB854E'
+ }
+ TestFrame {
+ time: 144
+ hash: 'B3F4A2165EC1EE971542B8EF89656CEA'
+ }
+ TestFrame {
+ time: 160
+ hash: 'AF3120FE262D2489C0ED33FBBEE1549F'
+ }
+ TestFrame {
+ time: 176
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 192
+ hash: '21F0B0437A999BBDE66A913032D495C2'
+ }
+ TestFrame {
+ time: 208
+ hash: '0809D32D5BC1BFCE199B1F39A1C68D4F'
+ }
+ TestFrame {
+ time: 224
+ hash: '022137587B39F5123835482178A1F1CF'
+ }
+ TestFrame {
+ time: 240
+ hash: '97566CE9558D13EA0780BCE233097B27'
+ }
+ TestFrame {
+ time: 256
+ hash: '96D79B07DA105B7F631ED61582B26F7E'
+ }
+ TestFrame {
+ time: 272
+ hash: 'F4732FF2DF93FE67CB850DEC34184924'
+ }
+ TestFrame {
+ time: 288
+ hash: '054E6E52F74A3E24F04E6AD0071F79F8'
+ }
+ TestFrame {
+ time: 304
+ hash: 'F541AF93A9FDE62E4BD1C91D30F91E65'
+ }
+ TestFrame {
+ time: 320
+ hash: 'C4F844EE71F23635BB3EC7375F6A134F'
+ }
+ TestFrame {
+ time: 336
+ hash: '3E52E06DB2BF78762BB9816FE6B105D9'
+ }
+ TestFrame {
+ time: 352
+ hash: 'D9604BE23A91327E6AB454609A9D4A13'
+ }
+ TestFrame {
+ time: 368
+ hash: 'DC98A9BDD99367C1E9B838D4BE489DCC'
+ }
+ TestFrame {
+ time: 384
+ hash: 'E87B00BFC2C2A75A4234EC02A057AD3A'
+ }
+ TestFrame {
+ time: 400
+ hash: '5BE4F5C67941EFB6FCEA363C79F1E321'
+ }
+ TestFrame {
+ time: 416
+ hash: '6CC9DE62A0C8FA5E42EAC1B01E99AC32'
+ }
+ TestFrame {
+ time: 432
+ hash: '62A7133012348F2EC3A388FB685ECC3F'
+ }
+ TestFrame {
+ time: 448
+ hash: '4AC43A03CC6F2020AB5F894D704092AC'
+ }
+ TestFrame {
+ time: 464
+ hash: 'C1A7B7D6D64AC5584C073C2881290696'
+ }
+ TestFrame {
+ time: 480
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 496
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 512
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 528
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 544
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 560
+ hash: 'C1A7B7D6D64AC5584C073C2881290696'
+ }
+ TestFrame {
+ time: 576
+ hash: 'C1A7B7D6D64AC5584C073C2881290696'
+ }
+ TestFrame {
+ time: 592
+ hash: '4AC43A03CC6F2020AB5F894D704092AC'
+ }
+ TestFrame {
+ time: 608
+ hash: '4AC43A03CC6F2020AB5F894D704092AC'
+ }
+ TestFrame {
+ time: 624
+ hash: 'FFD39C1122FE2F7877EF30591B539B40'
+ }
+ TestFrame {
+ time: 640
+ hash: '62A7133012348F2EC3A388FB685ECC3F'
+ }
+ TestFrame {
+ time: 656
+ hash: '45281A70021F81DBEF30334B1480DA1B'
+ }
+ TestFrame {
+ time: 672
+ hash: '6CC9DE62A0C8FA5E42EAC1B01E99AC32'
+ }
+ TestFrame {
+ time: 688
+ hash: '79EC710576427DF73DD03F39FBA6E2EB'
+ }
+ TestFrame {
+ time: 704
+ hash: '5BE4F5C67941EFB6FCEA363C79F1E321'
+ }
+ TestFrame {
+ time: 720
+ hash: '7D9096B1EB940C82A37BAF39EF3CCF3E'
+ }
+ TestFrame {
+ time: 736
+ hash: 'E87B00BFC2C2A75A4234EC02A057AD3A'
+ }
+ TestFrame {
+ time: 752
+ hash: 'DA60100DC55023C3BAB367D97C8F6A85'
+ }
+ TestFrame {
+ time: 768
+ hash: 'DC98A9BDD99367C1E9B838D4BE489DCC'
+ }
+ TestFrame {
+ time: 784
+ hash: '3F869538028A09020D5E8F528F4FB119'
+ }
+ TestFrame {
+ time: 800
+ hash: '9650FD0364C01B11E4F5DCCE51D008AF'
+ }
+ TestFrame {
+ time: 816
+ hash: '2CB09D9655ECC30AE6A591B28C0D355C'
+ }
+ TestFrame {
+ time: 832
+ hash: '4DB9BC6C11CAF1D77794C2EABB62A44E'
+ }
+ TestFrame {
+ time: 848
+ hash: 'CE2B5DD7418868ACF86FEA6AD19CC0C5'
+ }
+ TestFrame {
+ time: 864
+ hash: '7C27EF654E645679C90520D6CF00B0C4'
+ }
+ TestFrame {
+ time: 880
+ hash: 'AB3E211DF3EF7F5F7A8D712EDC891C0F'
+ }
+ TestFrame {
+ time: 896
+ hash: '19D2AE617A49B57DD012677E2834469C'
+ }
+ TestFrame {
+ time: 912
+ hash: '5025EB75C88F0760F637E0342B7F88A2'
+ }
+ TestFrame {
+ time: 928
+ hash: '005ACBEF952A8EE536E6308A48223E65'
+ }
+ TestFrame {
+ time: 944
+ hash: 'F1E0301430D153FB9D15EAFFDFCD5C58'
+ }
+ TestFrame {
+ time: 960
+ hash: '5F18A81707F23D377E81A27C1FC41CE9'
+ }
+ TestFrame {
+ time: 976
+ hash: 'BCC35497884C158396C7F60759D1FDA4'
+ }
+ TestFrame {
+ time: 992
+ hash: '7A4528B000A4EA142D1C77407FA1F581'
+ }
+ TestFrame {
+ time: 1008
+ hash: 'BA967A7D810A4531E577E5F6BD2DEF33'
+ }
+ TestFrame {
+ time: 1024
+ hash: 'F5AFD9CF8FFE27E9992454B9E68688CB'
+ }
+ TestFrame {
+ time: 1040
+ hash: '51D475C7F64A86D3A18FB115297A7B6B'
+ }
+ TestFrame {
+ time: 1056
+ hash: '49F5D6FD45C195A8D245B7FEFC1277AB'
+ }
+ TestFrame {
+ time: 1072
+ hash: 'F9B0B278659E3A0F78611E6B7F0F2176'
+ }
+ TestFrame {
+ time: 1088
+ hash: '0809D32D5BC1BFCE199B1F39A1C68D4F'
+ }
+ TestFrame {
+ time: 1104
+ hash: 'B7208D103B63A936DFF8DD8ED224237F'
+ }
+ TestFrame {
+ time: 1120
+ hash: 'A57C81049B0DC68090EC7C3327B9922C'
+ }
+ TestFrame {
+ time: 1136
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 1152
+ hash: 'AF3120FE262D2489C0ED33FBBEE1549F'
+ }
+ TestFrame {
+ time: 1168
+ hash: '0C20D12464ABBDC45041EA5D9F2719B1'
+ }
+ TestFrame {
+ time: 1184
+ hash: 'DD60CBAFF6F34027474E92315DBC0EBC'
+ }
+ TestFrame {
+ time: 1200
+ hash: '336D31586171F22D541B989D24B95CBB'
+ }
+ TestFrame {
+ time: 1216
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 1232
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 1248
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 1264
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 1280
+ hash: '336D31586171F22D541B989D24B95CBB'
+ }
+ TestFrame {
+ time: 1296
+ hash: 'F0D8132489C2F2EF760E905B3C093726'
+ }
+ TestFrame {
+ time: 1312
+ hash: '6D63FB5C8A80F0280E88B2CDF8641BB9'
+ }
+ TestFrame {
+ time: 1328
+ hash: 'DD60CBAFF6F34027474E92315DBC0EBC'
+ }
+ TestFrame {
+ time: 1344
+ hash: 'EF8941674CB61F54853DC33652BB854E'
+ }
+ TestFrame {
+ time: 1360
+ hash: 'BC426FB7C31751665B0D3F16E2CB0173'
+ }
+ TestFrame {
+ time: 1376
+ hash: '0C20D12464ABBDC45041EA5D9F2719B1'
+ }
+ TestFrame {
+ time: 1392
+ hash: '53AE93140252373EAA4D9DA73756BD8E'
+ }
+ TestFrame {
+ time: 1408
+ hash: '721D7061811B5439C2E8E395917494BC'
+ }
+ TestFrame {
+ time: 1424
+ hash: 'AF3120FE262D2489C0ED33FBBEE1549F'
+ }
+ TestFrame {
+ time: 1440
+ hash: 'A8B624EBFC9AB713D1CE55F318A6E90D'
+ }
+ TestFrame {
+ time: 1456
+ hash: 'A88A8129259F86DF5A73ADDC3649AD37'
+ }
+ TestFrame {
+ time: 1472
+ hash: 'A88A8129259F86DF5A73ADDC3649AD37'
+ }
+ TestFrame {
+ time: 1488
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 1504
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 1520
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 1536
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 1552
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 1568
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 1584
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 1600
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 1616
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 1632
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 1648
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 1664
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 1680
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 1696
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 1712
+ hash: 'A88A8129259F86DF5A73ADDC3649AD37'
+ }
+ TestFrame {
+ time: 1728
+ hash: 'A8B624EBFC9AB713D1CE55F318A6E90D'
+ }
+ TestFrame {
+ time: 1744
+ hash: 'A8B624EBFC9AB713D1CE55F318A6E90D'
+ }
+ TestFrame {
+ time: 1760
+ hash: 'AF3120FE262D2489C0ED33FBBEE1549F'
+ }
+ TestFrame {
+ time: 1776
+ hash: '721D7061811B5439C2E8E395917494BC'
+ }
+ TestFrame {
+ time: 1792
+ hash: 'B3F4A2165EC1EE971542B8EF89656CEA'
+ }
+ TestFrame {
+ time: 1808
+ hash: '0C20D12464ABBDC45041EA5D9F2719B1'
+ }
+ TestFrame {
+ time: 1824
+ hash: 'BC426FB7C31751665B0D3F16E2CB0173'
+ }
+ TestFrame {
+ time: 1840
+ hash: 'EF8941674CB61F54853DC33652BB854E'
+ }
+ TestFrame {
+ time: 1856
+ hash: 'DD60CBAFF6F34027474E92315DBC0EBC'
+ }
+ TestFrame {
+ time: 1872
+ hash: '6D63FB5C8A80F0280E88B2CDF8641BB9'
+ }
+ TestFrame {
+ time: 1888
+ hash: 'E74FE4A6BD92CBE8629C8BC8A870104D'
+ }
+ TestFrame {
+ time: 1904
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 1920
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 1936
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 1952
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 1968
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 1984
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 2000
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 2016
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 2032
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 2048
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 2064
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 2080
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2096
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2112
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2128
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2144
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2160
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2176
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2192
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 2208
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 2224
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 2240
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 2256
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 2272
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 2288
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 2304
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2320
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 2336
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2352
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2368
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2384
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2400
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 2416
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 2432
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2448
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2464
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2480
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 2496
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 2512
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 3504
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 3520
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 3536
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 3552
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 3568
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 3584
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 3600
+ hash: 'E74FE4A6BD92CBE8629C8BC8A870104D'
+ }
+ TestFrame {
+ time: 3616
+ hash: 'E11455D4E23A5A865E222A7ABA4BA4F9'
+ }
+ TestFrame {
+ time: 3632
+ hash: '8757668E56BE6449EC375F0B8FED1BE3'
+ }
+ TestFrame {
+ time: 3648
+ hash: '53AE93140252373EAA4D9DA73756BD8E'
+ }
+ TestFrame {
+ time: 3664
+ hash: 'A88A8129259F86DF5A73ADDC3649AD37'
+ }
+ TestFrame {
+ time: 3680
+ hash: '630D90EEF2673A69E8EBC4EF1BA40E81'
+ }
+ TestFrame {
+ time: 3696
+ hash: 'B7208D103B63A936DFF8DD8ED224237F'
+ }
+ TestFrame {
+ time: 3712
+ hash: '1516C3547C7CF64832B3BC7DA7C44521'
+ }
+ TestFrame {
+ time: 3728
+ hash: '49F5D6FD45C195A8D245B7FEFC1277AB'
+ }
+ TestFrame {
+ time: 3744
+ hash: 'F5AFD9CF8FFE27E9992454B9E68688CB'
+ }
+ TestFrame {
+ time: 3760
+ hash: '7A4528B000A4EA142D1C77407FA1F581'
+ }
+ TestFrame {
+ time: 3776
+ hash: '5F18A81707F23D377E81A27C1FC41CE9'
+ }
+ TestFrame {
+ time: 3792
+ hash: '005ACBEF952A8EE536E6308A48223E65'
+ }
+ TestFrame {
+ time: 3808
+ hash: '85C135EF72D3D25658A3663E69FFB7C2'
+ }
+ TestFrame {
+ time: 3824
+ hash: '7C27EF654E645679C90520D6CF00B0C4'
+ }
+ TestFrame {
+ time: 3840
+ hash: '20258F07C613958C32F783466771391A'
+ }
+ TestFrame {
+ time: 3856
+ hash: '9650FD0364C01B11E4F5DCCE51D008AF'
+ }
+ TestFrame {
+ time: 3872
+ hash: 'F340CDF60C6D4C29D26B7202A093EC70'
+ }
+ TestFrame {
+ time: 3888
+ hash: 'D754D35D0793F9F7D4F6249A874E4C45'
+ }
+ TestFrame {
+ time: 3904
+ hash: '79EC710576427DF73DD03F39FBA6E2EB'
+ }
+ TestFrame {
+ time: 3920
+ hash: '45281A70021F81DBEF30334B1480DA1B'
+ }
+ TestFrame {
+ time: 3936
+ hash: 'FFD39C1122FE2F7877EF30591B539B40'
+ }
+ TestFrame {
+ time: 3952
+ hash: '4AC43A03CC6F2020AB5F894D704092AC'
+ }
+ TestFrame {
+ time: 3968
+ hash: 'C1A7B7D6D64AC5584C073C2881290696'
+ }
+ TestFrame {
+ time: 3984
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 4000
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 4016
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 4032
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 4048
+ hash: '29ECE1BCA4D21FB5862091317D430A13'
+ }
+ TestFrame {
+ time: 4064
+ hash: 'C1A7B7D6D64AC5584C073C2881290696'
+ }
+ TestFrame {
+ time: 4080
+ hash: 'C1A7B7D6D64AC5584C073C2881290696'
+ }
+ TestFrame {
+ time: 4096
+ hash: '4AC43A03CC6F2020AB5F894D704092AC'
+ }
+ TestFrame {
+ time: 4112
+ hash: '4AC43A03CC6F2020AB5F894D704092AC'
+ }
+ TestFrame {
+ time: 4128
+ hash: 'FFD39C1122FE2F7877EF30591B539B40'
+ }
+ TestFrame {
+ time: 4144
+ hash: '62A7133012348F2EC3A388FB685ECC3F'
+ }
+ TestFrame {
+ time: 4160
+ hash: '45281A70021F81DBEF30334B1480DA1B'
+ }
+ TestFrame {
+ time: 4176
+ hash: '6CC9DE62A0C8FA5E42EAC1B01E99AC32'
+ }
+ TestFrame {
+ time: 4192
+ hash: '79EC710576427DF73DD03F39FBA6E2EB'
+ }
+ TestFrame {
+ time: 4208
+ hash: '5BE4F5C67941EFB6FCEA363C79F1E321'
+ }
+ TestFrame {
+ time: 4224
+ hash: '7D9096B1EB940C82A37BAF39EF3CCF3E'
+ }
+ TestFrame {
+ time: 4240
+ hash: 'E87B00BFC2C2A75A4234EC02A057AD3A'
+ }
+ TestFrame {
+ time: 4256
+ hash: 'DA60100DC55023C3BAB367D97C8F6A85'
+ }
+ TestFrame {
+ time: 4272
+ hash: 'DC98A9BDD99367C1E9B838D4BE489DCC'
+ }
+ TestFrame {
+ time: 4288
+ hash: 'B2C778A5EFF5F01EDC54F03D8B4DE8C7'
+ }
+ TestFrame {
+ time: 4304
+ hash: '9650FD0364C01B11E4F5DCCE51D008AF'
+ }
+ TestFrame {
+ time: 4320
+ hash: '2CB09D9655ECC30AE6A591B28C0D355C'
+ }
+ TestFrame {
+ time: 4336
+ hash: '4DB9BC6C11CAF1D77794C2EABB62A44E'
+ }
+ TestFrame {
+ time: 4352
+ hash: 'CE2B5DD7418868ACF86FEA6AD19CC0C5'
+ }
+ TestFrame {
+ time: 4368
+ hash: 'C4F844EE71F23635BB3EC7375F6A134F'
+ }
+ TestFrame {
+ time: 4384
+ hash: '4E1FDA8A0495EF968C1CFFB1257426D7'
+ }
+ TestFrame {
+ time: 4400
+ hash: '19D2AE617A49B57DD012677E2834469C'
+ }
+ TestFrame {
+ time: 4416
+ hash: 'F438E8D2C16B5DE677924C8411219B19'
+ }
+ TestFrame {
+ time: 4432
+ hash: '005ACBEF952A8EE536E6308A48223E65'
+ }
+ TestFrame {
+ time: 4448
+ hash: '87B71778D52CD8563D171151D4D32407'
+ }
+ TestFrame {
+ time: 4464
+ hash: '691CD8BF5C7802FF6C5024827A379FC6'
+ }
+ TestFrame {
+ time: 4480
+ hash: 'AB442C0173C3D221B6782D28001DAC77'
+ }
+ TestFrame {
+ time: 4496
+ hash: '6F886D4538704C2FAD4D84C68214109F'
+ }
+ TestFrame {
+ time: 4512
+ hash: '56D39F233FAE41C60499D6161F891CBC'
+ }
+ TestFrame {
+ time: 4528
+ hash: '95D987C3FD1352FB81C42C63634FE53B'
+ }
+ TestFrame {
+ time: 4544
+ hash: '96DC84C0C548021910E7C5B580179054'
+ }
+ TestFrame {
+ time: 4560
+ hash: 'DDB71CBD57F6E43744D533D4F72B08DB'
+ }
+ TestFrame {
+ time: 4576
+ hash: 'F7AB4B197BEA455B22F259913438D207'
+ }
+ TestFrame {
+ time: 4592
+ hash: '2AD64CB01C9D50E0118D5ECE0A644DF2'
+ }
+ TestFrame {
+ time: 4608
+ hash: '6579681C59DD571DF0EE4429D74FB5C7'
+ }
+ TestFrame {
+ time: 4624
+ hash: '630D90EEF2673A69E8EBC4EF1BA40E81'
+ }
+ TestFrame {
+ time: 4640
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 4656
+ hash: '721D7061811B5439C2E8E395917494BC'
+ }
+ TestFrame {
+ time: 4672
+ hash: 'BC426FB7C31751665B0D3F16E2CB0173'
+ }
+ TestFrame {
+ time: 4688
+ hash: 'E11455D4E23A5A865E222A7ABA4BA4F9'
+ }
+ TestFrame {
+ time: 4704
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 4720
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 4736
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 4752
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 4768
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 4784
+ hash: '336D31586171F22D541B989D24B95CBB'
+ }
+ TestFrame {
+ time: 4800
+ hash: 'F0D8132489C2F2EF760E905B3C093726'
+ }
+ TestFrame {
+ time: 4816
+ hash: 'E11455D4E23A5A865E222A7ABA4BA4F9'
+ }
+ TestFrame {
+ time: 4832
+ hash: 'DD60CBAFF6F34027474E92315DBC0EBC'
+ }
+ TestFrame {
+ time: 4848
+ hash: '8757668E56BE6449EC375F0B8FED1BE3'
+ }
+ TestFrame {
+ time: 4864
+ hash: 'BC426FB7C31751665B0D3F16E2CB0173'
+ }
+ TestFrame {
+ time: 4880
+ hash: 'B3F4A2165EC1EE971542B8EF89656CEA'
+ }
+ TestFrame {
+ time: 4896
+ hash: '53AE93140252373EAA4D9DA73756BD8E'
+ }
+ TestFrame {
+ time: 4912
+ hash: '721D7061811B5439C2E8E395917494BC'
+ }
+ TestFrame {
+ time: 4928
+ hash: 'AF3120FE262D2489C0ED33FBBEE1549F'
+ }
+ TestFrame {
+ time: 4944
+ hash: 'A8B624EBFC9AB713D1CE55F318A6E90D'
+ }
+ TestFrame {
+ time: 4960
+ hash: 'A88A8129259F86DF5A73ADDC3649AD37'
+ }
+ TestFrame {
+ time: 4976
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 4992
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 5008
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 5024
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 5040
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 5056
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 5072
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 5088
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 5104
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 5120
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 5136
+ hash: '1373545E43FFF7251CEC9E8375EA267F'
+ }
+ TestFrame {
+ time: 5152
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 5168
+ hash: 'E553F365912586C6408C8C53B1B7D118'
+ }
+ TestFrame {
+ time: 5184
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 5200
+ hash: '3DB5E30EF19EA693C21CCF72892C4390'
+ }
+ TestFrame {
+ time: 5216
+ hash: 'A88A8129259F86DF5A73ADDC3649AD37'
+ }
+ TestFrame {
+ time: 5232
+ hash: 'A8B624EBFC9AB713D1CE55F318A6E90D'
+ }
+ TestFrame {
+ time: 5248
+ hash: 'AF3120FE262D2489C0ED33FBBEE1549F'
+ }
+ TestFrame {
+ time: 5264
+ hash: '721D7061811B5439C2E8E395917494BC'
+ }
+ TestFrame {
+ time: 5280
+ hash: '53AE93140252373EAA4D9DA73756BD8E'
+ }
+ TestFrame {
+ time: 5296
+ hash: 'B3F4A2165EC1EE971542B8EF89656CEA'
+ }
+ TestFrame {
+ time: 5312
+ hash: '0C20D12464ABBDC45041EA5D9F2719B1'
+ }
+ TestFrame {
+ time: 5328
+ hash: '8757668E56BE6449EC375F0B8FED1BE3'
+ }
+ TestFrame {
+ time: 5344
+ hash: 'EF8941674CB61F54853DC33652BB854E'
+ }
+ TestFrame {
+ time: 5360
+ hash: 'E11455D4E23A5A865E222A7ABA4BA4F9'
+ }
+ TestFrame {
+ time: 5376
+ hash: '6D63FB5C8A80F0280E88B2CDF8641BB9'
+ }
+ TestFrame {
+ time: 5392
+ hash: 'E74FE4A6BD92CBE8629C8BC8A870104D'
+ }
+ TestFrame {
+ time: 5408
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5424
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 5440
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 5456
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 5472
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5488
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 5504
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 5520
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 5536
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 5552
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 5568
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 5584
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5600
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5616
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5632
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5648
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5664
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5680
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5696
+ hash: '3042003C067B257DE2CB32F650DDE693'
+ }
+ TestFrame {
+ time: 5712
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 5728
+ hash: 'A725B59B4947357546BBFC7DF3D830AF'
+ }
+ TestFrame {
+ time: 5744
+ hash: 'CE57E27AF329EBA4FAC3AB891F0407CE'
+ }
+ TestFrame {
+ time: 5760
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 5776
+ hash: '41BA853C3403F68A23E708DF82E21C53'
+ }
+ TestFrame {
+ time: 5792
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 5808
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5824
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+ TestFrame {
+ time: 5840
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5856
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5872
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5888
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5904
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 5920
+ hash: 'DCF2867C127E041970047EC8F3EDC04F'
+ }
+ TestFrame {
+ time: 5936
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5952
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5968
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 5984
+ hash: '675EBBDD22DD22CE45993DF4AF1ACFE9'
+ }
+ TestFrame {
+ time: 6000
+ hash: 'A350B70C5238A340E85FD4A3EC0390A3'
+ }
+}
diff --git a/tests/auto/declarative/visual/pauseAnimation/pauseAnimation.qml b/tests/auto/declarative/visual/pauseAnimation/pauseAnimation.qml
new file mode 100644
index 0000000..5c00f58
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/pauseAnimation.qml
@@ -0,0 +1,28 @@
+Rect {
+ id: rect
+ width: 120
+ height: 200
+ color: "white"
+ Image {
+ id: img
+ source: "pics/qtlogo.png"
+ x: 60-width/2
+ y: 200-height
+ y: SequentialAnimation {
+ running: true
+ repeat: true
+ NumericAnimation {
+ to: 0; duration: 500
+ easing: "easeInOutQuad"
+ }
+ NumericAnimation {
+ to: 200-img.height
+ easing: "easeOutBounce"
+ duration: 2000
+ }
+ PauseAnimation {
+ duration: 1000
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.png b/tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.png
Binary files differ
diff --git a/tests/auto/declarative/visual/pauseAnimation/test b/tests/auto/declarative/visual/pauseAnimation/test
new file mode 100644
index 0000000..85bc3c1
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/test
@@ -0,0 +1 @@
+pauseAnimation.qml
diff --git a/tests/auto/declarative/visual/qfxtext/elide/data/raster/image0.png b/tests/auto/declarative/visual/qfxtext/elide/data/raster/image0.png
new file mode 100644
index 0000000..05dc9ab
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/qfxtext/elide/data/raster/manifest.qml b/tests/auto/declarative/visual/qfxtext/elide/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/qfxtext/elide/elide.qml b/tests/auto/declarative/visual/qfxtext/elide/elide.qml
new file mode 100644
index 0000000..23e6885
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/elide.qml
@@ -0,0 +1,33 @@
+Rect {
+ width: contents.width
+ height: contents.height
+ VerticalLayout {
+ width: 80
+ height: Text.height*4
+ Text {
+ elide: "ElideLeft"
+ text: "aaa bbb ccc ddd eee fff"
+ width: 80
+ color: "white"
+ id: Text
+ }
+ Text {
+ elide: "ElideMiddle"
+ text: "aaa bbb ccc ddd eee fff"
+ width: 80
+ color: "white"
+ }
+ Text {
+ elide: "ElideRight"
+ text: "aaa bbb ccc ddd eee fff"
+ width: 80
+ color: "white"
+ }
+ Text {
+ elide: "ElideNone"
+ text: "aaa bbb ccc ddd eee fff"
+ width: 80
+ color: "white"
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/qfxtext/elide/test b/tests/auto/declarative/visual/qfxtext/elide/test
new file mode 100644
index 0000000..bde7c7c
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/test
@@ -0,0 +1 @@
+elide.qml
diff --git a/tests/auto/declarative/visual/repeater/basic1/basic1.qml b/tests/auto/declarative/visual/repeater/basic1/basic1.qml
new file mode 100644
index 0000000..ba8f44d
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/basic1.qml
@@ -0,0 +1,26 @@
+Rect {
+ color: "blue"
+ width: 300
+ height: 200
+ id: Page
+ HorizontalLayout {
+ Repeater {
+ component: Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ dataSource: ListModel {
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic1/data/raster/image0.png b/tests/auto/declarative/visual/repeater/basic1/data/raster/image0.png
new file mode 100644
index 0000000..868eaa3
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic1/data/raster/manifest.qml b/tests/auto/declarative/visual/repeater/basic1/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic1/test b/tests/auto/declarative/visual/repeater/basic1/test
new file mode 100644
index 0000000..49fcf5a
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/test
@@ -0,0 +1 @@
+basic1.qml
diff --git a/tests/auto/declarative/visual/repeater/basic2/basic2.qml b/tests/auto/declarative/visual/repeater/basic2/basic2.qml
new file mode 100644
index 0000000..d975ea4
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/basic2.qml
@@ -0,0 +1,30 @@
+Rect {
+ color: "blue"
+ width: 300
+ height: 200
+ id: Page
+ Component {
+ id: Delegate
+ Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+ HorizontalLayout {
+ Repeater {
+ component: Delegate
+ dataSource: ListModel {
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic2/data/raster/image0.png b/tests/auto/declarative/visual/repeater/basic2/data/raster/image0.png
new file mode 100644
index 0000000..868eaa3
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic2/data/raster/manifest.qml b/tests/auto/declarative/visual/repeater/basic2/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic2/test b/tests/auto/declarative/visual/repeater/basic2/test
new file mode 100644
index 0000000..eb79495
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/test
@@ -0,0 +1 @@
+basic2.qml
diff --git a/tests/auto/declarative/visual/repeater/basic3/basic3.qml b/tests/auto/declarative/visual/repeater/basic3/basic3.qml
new file mode 100644
index 0000000..cecba33
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/basic3.qml
@@ -0,0 +1,28 @@
+Rect {
+ color: "blue"
+ width: 300
+ height: 200
+ id: Page
+ ListModel {
+ id: DataSource
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ HorizontalLayout {
+ Repeater {
+ dataSource: DataSource
+ component: Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic3/data/raster/image0.png b/tests/auto/declarative/visual/repeater/basic3/data/raster/image0.png
new file mode 100644
index 0000000..868eaa3
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic3/data/raster/manifest.qml b/tests/auto/declarative/visual/repeater/basic3/data/raster/manifest.qml
new file mode 100644
index 0000000..47d36c3
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/data/raster/manifest.qml
@@ -0,0 +1,13 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+ TestKey {
+ time: 1296
+ type: 6
+ modifiers: 0
+ key: 16777251
+ text: ''
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic3/test b/tests/auto/declarative/visual/repeater/basic3/test
new file mode 100644
index 0000000..9ec306b
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/test
@@ -0,0 +1 @@
+basic3.qml
diff --git a/tests/auto/declarative/visual/repeater/basic4/basic4.qml b/tests/auto/declarative/visual/repeater/basic4/basic4.qml
new file mode 100644
index 0000000..050a2c5
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/basic4.qml
@@ -0,0 +1,32 @@
+Rect {
+ color: "blue"
+ width: 300
+ height: 200
+ id: Page
+ ListModel {
+ id: DataSource
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ Component {
+ id: Delegate
+ Rect {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+ HorizontalLayout {
+ Repeater {
+ dataSource: DataSource
+ component: Delegate
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic4/data/raster/image0.png b/tests/auto/declarative/visual/repeater/basic4/data/raster/image0.png
new file mode 100644
index 0000000..868eaa3
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic4/data/raster/manifest.qml b/tests/auto/declarative/visual/repeater/basic4/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/repeater/basic4/test b/tests/auto/declarative/visual/repeater/basic4/test
new file mode 100644
index 0000000..2a7f227
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/test
@@ -0,0 +1 @@
+basic4.qml
diff --git a/tests/auto/declarative/visual/runtests.sh b/tests/auto/declarative/visual/runtests.sh
new file mode 100755
index 0000000..4380884
--- /dev/null
+++ b/tests/auto/declarative/visual/runtests.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+export QFX_USE_SIMPLECANVAS=1
+for a in `cat tests`; do ./tst_visual -testdir $a; done
diff --git a/tests/auto/declarative/visual/tests b/tests/auto/declarative/visual/tests
new file mode 100644
index 0000000..ca72e9e
--- /dev/null
+++ b/tests/auto/declarative/visual/tests
@@ -0,0 +1,11 @@
+ListView/basic1
+ListView/basic2
+ListView/basic3
+ListView/basic4
+bindinganimation
+repeater/basic1
+repeater/basic2
+repeater/basic3
+repeater/basic4
+webview/autosize
+qfxtext/elide
diff --git a/tests/auto/declarative/visual/tst_visual.cpp b/tests/auto/declarative/visual/tst_visual.cpp
new file mode 100644
index 0000000..f540e62
--- /dev/null
+++ b/tests/auto/declarative/visual/tst_visual.cpp
@@ -0,0 +1,74 @@
+#include <qtest.h>
+#include <QFxView>
+#include <QApplication>
+#include <QFxTestView>
+#include <QFile>
+
+static QString testdir;
+class tst_visual : public QObject
+{
+ Q_OBJECT
+public:
+ tst_visual() {}
+
+private slots:
+ void visual();
+};
+
+#ifdef QT_OPENGL_ES
+#define RASTER_TESTDIR "/data/opengl"
+#else
+#define RASTER_TESTDIR "/data/raster"
+#endif
+
+void tst_visual::visual()
+{
+ QVERIFY(!testdir.isEmpty());
+
+ QString filename = QLatin1String(QT_TEST_SOURCE_DIR) + "/" + testdir + "/test";
+ qWarning() << "Using config:" << filename;
+ QFile configFile(filename);
+ QVERIFY(configFile.open(QIODevice::ReadOnly));
+
+ QString testfile = configFile.readLine().trimmed();
+ QVERIFY(!testfile.isEmpty());
+
+ if(testfile.startsWith("QTDIR/")) {
+ testfile.remove(0, 6);
+ testfile.prepend(QLatin1String(QT_TEST_SOURCE_DIR) + "/../../../../");
+ } else {
+ testfile.prepend(QLatin1String(QT_TEST_SOURCE_DIR) + "/" + testdir + "/");
+ }
+
+ QFxTestView *view = new QFxTestView(testfile, QLatin1String(QT_TEST_SOURCE_DIR) + "/" + testdir + RASTER_TESTDIR);
+ QVERIFY(view->runTest());
+}
+
+#include <QtTest/qtest_gui.h>
+
+int main(int argc, char *argv[])
+{
+ int newArgc = 1;
+ char **newArgv = new char*[argc];
+
+ newArgv[0] = argv[0];
+
+ QApplication app(newArgc, newArgv);
+
+ for(int ii = 1; ii < argc; ii++) {
+ if(QLatin1String(argv[ii]) == "-testdir" && (ii + 1) < argc) {
+ testdir = QLatin1String(argv[ii + 1]);
+ ii++;
+ } else {
+ newArgv[newArgc++] = argv[ii];
+ }
+ }
+
+ tst_visual tc;
+ int rv = QTest::qExec(&tc, newArgc, newArgv);
+
+ delete [] newArgv;
+ return rv;
+}
+
+#include "tst_visual.moc"
diff --git a/tests/auto/declarative/visual/visual.pro b/tests/auto/declarative/visual/visual.pro
new file mode 100644
index 0000000..203b691
--- /dev/null
+++ b/tests/auto/declarative/visual/visual.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_visual.cpp
+
+DEFINES += QT_TEST_SOURCE_DIR=\"\\\"$$PWD\\\"\"
diff --git a/tests/auto/declarative/visual/webview/autosize/data/raster/image0.png b/tests/auto/declarative/visual/webview/autosize/data/raster/image0.png
new file mode 100644
index 0000000..206952d
--- /dev/null
+++ b/tests/auto/declarative/visual/webview/autosize/data/raster/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/webview/autosize/data/raster/manifest.qml b/tests/auto/declarative/visual/webview/autosize/data/raster/manifest.qml
new file mode 100644
index 0000000..6d900f5
--- /dev/null
+++ b/tests/auto/declarative/visual/webview/autosize/data/raster/manifest.qml
@@ -0,0 +1,6 @@
+TestLog {
+ TestFullFrame {
+ time: 0
+ frameId: 0
+ }
+}
diff --git a/tests/auto/declarative/visual/webview/autosize/test b/tests/auto/declarative/visual/webview/autosize/test
new file mode 100644
index 0000000..446d3f9
--- /dev/null
+++ b/tests/auto/declarative/visual/webview/autosize/test
@@ -0,0 +1 @@
+QTDIR/examples/declarative/webview/autosize.qml
diff --git a/tests/auto/dynamicobject/dynamicobject.pro b/tests/auto/dynamicobject/dynamicobject.pro
new file mode 100644
index 0000000..1b2a075
--- /dev/null
+++ b/tests/auto/dynamicobject/dynamicobject.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+SOURCES += tst_qobject.cpp qmetaobjectbuilder.cpp qdynamicmetaobject.cpp
+HEADERS += qmetaobjectbuilder.h qdynamicmetaobject.h
+
+QT = core
+
diff --git a/tests/auto/dynamicobject/qdynamicmetaobject.cpp b/tests/auto/dynamicobject/qdynamicmetaobject.cpp
new file mode 100644
index 0000000..b44555f
--- /dev/null
+++ b/tests/auto/dynamicobject/qdynamicmetaobject.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+****************************************************************************/
+
+#include <qcoreapplication.h>
+
+#include <qmetaobject.h>
+
+#include "qobject.h"
+#include "private/qobject_p.h"
+#include "qmetaobjectbuilder.h"
+#include "qdynamicmetaobject.h"
+
+class QDynamicMetaObjectData
+{
+public:
+ QDynamicMetaObjectData() : ref(1), baseMeta(0), meta(0) {}
+ ~QDynamicMetaObjectData() { qFree(meta); }
+
+ QAtomicInt ref;
+ QMetaObjectBuilder builder;
+ const QMetaObject *baseMeta;
+ QMetaObject *meta;
+};
+
+/*!
+ \class QDynamicMetaObject
+ \brief The QDynamicMetaObject class allows adding signals, slots and properties to
+ QObjects at runtime.
+
+ Any QObject derived class can be extended by creating a QDynamicMetaObject
+ based on the QObject's QMetaObject.
+
+ QObject::setDynamicMetaObject() is called to set the dynamic meta-object for
+ the QObject.
+
+ \sa QMetaObject
+*/
+
+/*!
+ Constructs a dynamic meta-object based on \a baseMetaObject.
+
+ QObject::setDynamicMetaObject() should be called to install it.
+*/
+QDynamicMetaObject::QDynamicMetaObject(const QMetaObject *baseMetaObject)
+{
+ data_ptr = new QDynamicMetaObjectData;
+ data_ptr->baseMeta = baseMetaObject;
+ data_ptr->builder.setSuperClass(data_ptr->baseMeta);
+ data_ptr->builder.setClassName(data_ptr->baseMeta->className());
+ updateMetaData();
+}
+
+/*!
+ Constructs a dynamic meta-object that is a copy of \a other.
+*/
+QDynamicMetaObject::QDynamicMetaObject(const QDynamicMetaObject &other)
+{
+ data_ptr = other.data_ptr;
+ data_ptr->ref.ref();
+}
+
+/*!
+ Destroys the dynamic meta-ovject.
+*/
+QDynamicMetaObject::~QDynamicMetaObject()
+{
+ if (!data_ptr->ref.deref())
+ delete data_ptr;
+}
+
+/*!
+ Copies the dynamic metadata from \a that. The static metadata must be identical,
+ i.e. the dynamic metadata is constructed for the same class.
+*/
+QDynamicMetaObject &QDynamicMetaObject::operator=(const QDynamicMetaObject &that)
+{
+ Q_ASSERT(data_ptr->baseMeta == that.data_ptr->baseMeta);
+ qAtomicAssign(data_ptr, that.data_ptr);
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QDynamicMetaObject &QDynamicMetaObject::operator=(const QMetaObject &that)
+{
+ static_cast<QMetaObject*>(this)->d = that.d;
+ return *this;
+}
+
+/*!
+ \internal
+*/
+void QDynamicMetaObject::detach()
+{
+ if (data_ptr->ref == 1)
+ return;
+
+ //XXX copy builder faster.
+ QByteArray buf;
+ QDataStream ds(&buf, QIODevice::ReadWrite);
+ data_ptr->builder.serialize(ds);
+ if (!data_ptr->ref.deref())
+ delete data_ptr;
+ data_ptr = new QDynamicMetaObjectData;
+ QMap<QByteArray, const QMetaObject *> refs;
+ data_ptr->builder.deserialize(ds, refs);
+ updateMetaData();
+}
+
+/*!
+ Adds the signal with \a signature.
+*/
+void QDynamicMetaObject::addSignal(const char *signature)
+{
+ detach();
+ data_ptr->builder.addSignal(signature);
+ updateMetaData();
+}
+
+/*!
+ Adds the signal with \a signature and sets the \a parameterNames.
+*/
+void QDynamicMetaObject::addSignal(const char *signature, const QList<QByteArray> &parameterNames)
+{
+ detach();
+ QMetaMethodBuilder method = data_ptr->builder.addSignal(signature);
+ method.setParameterNames(parameterNames);
+ updateMetaData();
+}
+
+/*!
+ Adds the slot with \a signature.
+*/
+void QDynamicMetaObject::addSlot(const char *signature)
+{
+ detach();
+ data_ptr->builder.addSlot(signature);
+ updateMetaData();
+}
+
+
+/*!
+ Adds the slot with \a signature and sets the \a parameterNames.
+*/
+void QDynamicMetaObject::addSlot(const char *signature, const QList<QByteArray> &parameterNames)
+{
+ detach();
+ QMetaMethodBuilder method = data_ptr->builder.addSlot(signature);
+ method.setParameterNames(parameterNames);
+ updateMetaData();
+}
+
+/*!
+ Adds the property with \a name of \a type. If \a notifier specified it is
+ set as the change notifier for the property.
+*/
+void QDynamicMetaObject::addProperty(const char *name, const char *type, const char *notifier)
+{
+ int notifierId = -1;
+ if (notifier)
+ notifierId = data_ptr->builder.indexOfSignal(notifier);
+ data_ptr->builder.addProperty(name, type, notifierId);
+ updateMetaData();
+}
+
+/*!
+ Adds the property with \a name of \a type. If \a notifierId is specified it is
+ set as the change notifier for the property.
+*/
+void QDynamicMetaObject::addProperty(const char *name, const char *type, int notifierId)
+{
+ data_ptr->builder.addProperty(name, type, notifierId);
+ updateMetaData();
+}
+
+/*!
+ \reimp
+*/
+int QDynamicMetaObject::metaCall(QObject *object, QMetaObject::Call _c, int _id, void **_a)
+{
+ if (_c == QMetaObject::InvokeMetaMethod && _id >= data_ptr->baseMeta->methodCount()) {
+ QMetaMethod metaMethod = method(_id);
+ if (metaMethod.methodType() == QMetaMethod::Slot) {
+ if (metaMethod.parameterTypes().count() == 0) {
+ static QList<QVariant> noArgs;
+ callSlot(object, _id, noArgs);
+ } else {
+ QList<QVariant> args;
+ for (int i = 0; i < metaMethod.parameterTypes().count(); ++i) {
+ int typeId = QVariant::nameToType(metaMethod.parameterTypes().at(i));
+ args.append(QVariant(typeId, _a[i+1]));
+ }
+ callSlot(object, _id, args);
+ }
+ } else if (metaMethod.methodType() == QMetaMethod::Signal)
+ activate(object, _id, _a);
+ _id = -1;
+ } else if (_c == QMetaObject::ReadProperty && _id >= data_ptr->baseMeta->propertyCount()) {
+ *(reinterpret_cast<QVariant*>(_a[1])) = readProperty(object, _id);
+ _id = -1;
+ } else if (_c == QMetaObject::WriteProperty && _id >= data_ptr->baseMeta->propertyCount()) {
+ writeProperty(object, _id, *(reinterpret_cast<QVariant*>(_a[1])));
+ if (property(_id).hasNotifySignal())
+ activate(object, property(_id).notifySignalIndex(), 0);
+ _id = -1;
+ } else {
+ _id = object->qt_metacall(_c, _id, _a);
+ }
+
+ return _id;
+}
+
+/*!
+ The slot with \a id has been called for \a object. The parameters are available via \a args.
+*/
+void QDynamicMetaObject::callSlot(QObject *object, int id, const QList<QVariant> &args)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(id);
+ Q_UNUSED(args);
+}
+
+/*!
+ The \a value of property with \a id has changed for \a object.
+*/
+void QDynamicMetaObject::writeProperty(QObject *object, int id, const QVariant &value)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(id);
+ Q_UNUSED(value);
+}
+
+/*!
+ Return the value of the property with \a id belonging to \a object.
+*/
+QVariant QDynamicMetaObject::readProperty(QObject *object, int id) const
+{
+ Q_UNUSED(object);
+ Q_UNUSED(id);
+ return QVariant();
+}
+
+void QDynamicMetaObject::updateMetaData()
+{
+ qFree(data_ptr->meta);
+ data_ptr->meta = data_ptr->builder.toMetaObject();
+ *this = *data_ptr->meta;
+}
+
diff --git a/tests/auto/dynamicobject/qdynamicmetaobject.h b/tests/auto/dynamicobject/qdynamicmetaobject.h
new file mode 100644
index 0000000..747d118
--- /dev/null
+++ b/tests/auto/dynamicobject/qdynamicmetaobject.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+****************************************************************************/
+
+#ifndef _QDYNAMICMETAOBJECT_H_
+#define _QDYNAMICMETAOBJECT_H_
+
+#include <qmetaobject.h>
+#include <qobject.h>
+
+class QDynamicMetaObjectData;
+
+class QDynamicMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QDynamicMetaObject(const QMetaObject *baseMetaObject);
+ QDynamicMetaObject(const QDynamicMetaObject &other);
+ virtual ~QDynamicMetaObject();
+
+ QDynamicMetaObject &operator=(const QDynamicMetaObject &that);
+
+ void addSignal(const char *sigName);
+ void addSignal(const char *sigName, const QList<QByteArray> &parameterNames);
+ void addSlot(const char *slotName);
+ void addSlot(const char *slotName, const QList<QByteArray> &parameterNames);
+ void addProperty(const char *name, const char *type, const char *notifier);
+ void addProperty(const char *name, const char *type, int notifierId=-1);
+
+protected:
+ virtual int metaCall(QObject *object, QMetaObject::Call _c, int _id, void **_a);
+ virtual void callSlot(QObject *object, int id, const QList<QVariant> &args);
+ virtual void writeProperty(QObject *object, int id, const QVariant &value);
+ virtual QVariant readProperty(QObject *object, int id) const;
+
+private:
+ void detach();
+ void updateMetaData();
+ QDynamicMetaObject &operator=(const QMetaObject &that);
+
+private:
+ QDynamicMetaObjectData *data_ptr;
+};
+
+#endif
diff --git a/tests/auto/dynamicobject/qmetaobjectbuilder.cpp b/tests/auto/dynamicobject/qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..3927f6a
--- /dev/null
+++ b/tests/auto/dynamicobject/qmetaobjectbuilder.cpp
@@ -0,0 +1,2347 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetaobjectbuilder.h"
+#include <QDebug>
+
+/*!
+ \class QMetaObjectBuilder
+ \brief The QMetaObjectBuilder class supports the building of QMetaObject objects at runtime.
+
+ See the QDynamicMetaObject class documentation for an example
+ of using this class.
+
+ \sa QDynamicMetaObject, QDynamicObject
+*/
+
+/*!
+ \enum QMetaObjectBuilder::AddMember
+ This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
+
+ \value ClassName Add the class name.
+ \value SuperClass Add the super class.
+ \value Methods Add methods that aren't signals or slots.
+ \value Signals Add signals.
+ \value Slots Add slots.
+ \value Constructors Add constructors.
+ \value Properties Add properties.
+ \value Enumerators Add enumerators.
+ \value ClassInfos Add items of class information.
+ \value RelatedMetaObjects Add related meta objects.
+ \value StaticMetacall Add the static metacall function.
+ \value PublicMethods Add public methods (ignored for signals).
+ \value ProtectedMethods Add protected methods (ignored for signals).
+ \value PrivateMethods All private methods (ignored for signals).
+ \value AllMembers Add all members.
+ \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
+*/
+
+// copied from qmetaobject.cpp
+// do not touch without touching the moc as well
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+};
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData;
+};
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+// end of copied lines from qmetaobject.cpp
+
+class QMetaMethodBuilderPrivate
+{
+public:
+ QMetaMethodBuilderPrivate
+ (QMetaMethod::MethodType _methodType,
+ const QByteArray& _signature,
+ const QByteArray& _returnType = QByteArray(),
+ QMetaMethod::Access _access = QMetaMethod::Public)
+ : signature(QMetaObject::normalizedSignature(_signature.constData())),
+ returnType(QMetaObject::normalizedType(_returnType)),
+ attributes(((int)_access) | (((int)_methodType) << 2))
+ {
+ }
+
+ QByteArray signature;
+ QByteArray returnType;
+ QList<QByteArray> parameterNames;
+ QByteArray tag;
+ int attributes;
+
+ QMetaMethod::MethodType methodType() const
+ {
+ return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
+ }
+
+ QMetaMethod::Access access() const
+ {
+ return (QMetaMethod::Access)(attributes & AccessMask);
+ }
+
+ void setAccess(QMetaMethod::Access value)
+ {
+ attributes = ((attributes & ~AccessMask) | (int)value);
+ }
+};
+
+class QMetaPropertyBuilderPrivate
+{
+public:
+ QMetaPropertyBuilderPrivate
+ (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1)
+ : name(_name),
+ type(QMetaObject::normalizedType(_type.constData())),
+ flags(Readable | Writable), notifySignal(-1)
+ {
+ if (notifierIdx >= 0) {
+ flags |= Notify;
+ notifySignal = notifierIdx;
+ }
+ }
+
+ QByteArray name;
+ QByteArray type;
+ int flags;
+ int notifySignal;
+
+ bool flag(int f) const
+ {
+ return ((flags & f) != 0);
+ }
+
+ void setFlag(int f, bool value)
+ {
+ if (value)
+ flags |= f;
+ else
+ flags &= ~f;
+ }
+};
+
+class QMetaEnumBuilderPrivate
+{
+public:
+ QMetaEnumBuilderPrivate(const QByteArray& _name)
+ : name(_name), isFlag(false)
+ {
+ }
+
+ QByteArray name;
+ bool isFlag;
+ QList<QByteArray> keys;
+ QList<int> values;
+};
+
+class QMetaObjectBuilderPrivate
+{
+public:
+ QMetaObjectBuilderPrivate()
+ {
+ superClass = &QObject::staticMetaObject;
+ staticMetacallFunction = 0;
+ }
+
+ QByteArray className;
+ const QMetaObject *superClass;
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
+ QList<QMetaMethodBuilderPrivate> methods;
+ QList<QMetaMethodBuilderPrivate> constructors;
+ QList<QMetaPropertyBuilderPrivate> properties;
+ QList<QByteArray> classInfoNames;
+ QList<QByteArray> classInfoValues;
+ QList<QMetaEnumBuilderPrivate> enumerators;
+ QList<const QMetaObject *> relatedMetaObjects;
+};
+
+/*!
+ Constructs a new QMetaObjectBuilder.
+*/
+QMetaObjectBuilder::QMetaObjectBuilder()
+{
+ d = new QMetaObjectBuilderPrivate();
+}
+
+/*!
+ Constructs a new QMetaObjectBuilder which is a copy of the
+ meta object information in \a prototype. Note: the super class
+ contents for \a prototype are not copied, only the immediate
+ class that is defined by \a prototype.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+
+ \sa addMetaObject()
+*/
+QMetaObjectBuilder::QMetaObjectBuilder
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ d = new QMetaObjectBuilderPrivate();
+ addMetaObject(prototype, members);
+}
+
+/*!
+ Destroys this meta object builder.
+*/
+QMetaObjectBuilder::~QMetaObjectBuilder()
+{
+ delete d;
+}
+
+/*!
+ Returns the name of the class being constructed by this
+ meta object builder. The default value is an empty QByteArray.
+
+ \sa setClassName(), superClass()
+*/
+QByteArray QMetaObjectBuilder::className() const
+{
+ return d->className;
+}
+
+/*!
+ Sets the \a name of the class being constructed by this
+ meta object builder.
+
+ \sa className(), setSuperClass()
+*/
+void QMetaObjectBuilder::setClassName(const QByteArray& name)
+{
+ d->className = name;
+}
+
+/*!
+ Returns the superclass meta object of the class being constructed
+ by this meta object builder. The default value is the meta object
+ for QObject.
+
+ \sa setSuperClass(), className()
+*/
+const QMetaObject *QMetaObjectBuilder::superClass() const
+{
+ return d->superClass;
+}
+
+/*!
+ Sets the superclass meta object of the class being constructed
+ by this meta object builder to \a meta. The \a meta parameter
+ must not be null.
+
+ \sa superClass(), setClassName()
+*/
+void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ d->superClass = meta;
+}
+
+/*!
+ Returns the number of methods in this class, excluding the number
+ of methods in the base class. These include signals and slots
+ as well as normal member functions.
+
+ \sa addMethod(), method(), removeMethod(), indexOfMethod()
+*/
+int QMetaObjectBuilder::methodCount() const
+{
+ return d->methods.size();
+}
+
+/*!
+ Returns the number of constructors in this class.
+
+ \sa addConstructor(), constructor(), removeConstructor(), indexOfConstructor()
+*/
+int QMetaObjectBuilder::constructorCount() const
+{
+ return d->constructors.size();
+}
+
+/*!
+ Returns the number of properties in this class, excluding the number
+ of properties in the base class.
+
+ \sa addProperty(), property(), removeProperty(), indexOfProperty()
+*/
+int QMetaObjectBuilder::propertyCount() const
+{
+ return d->properties.size();
+}
+
+/*!
+ Returns the number of enumerators in this class, excluding the
+ number of enumerators in the base class.
+
+ \sa addEnumerator(), enumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+int QMetaObjectBuilder::enumeratorCount() const
+{
+ return d->enumerators.size();
+}
+
+/*!
+ Returns the number of items of class information in this class,
+ exclusing the number of items of class information in the base class.
+
+ \sa addClassInfo(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::classInfoCount() const
+{
+ return d->classInfoNames.size();
+}
+
+/*!
+ Returns the number of related meta objects that are associated
+ with this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa addRelatedMetaObject(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::relatedMetaObjectCount() const
+{
+ return d->relatedMetaObjects.size();
+}
+
+/*!
+ Adds a new public method to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the method. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class with the specified
+ \a signature and \a returnType. Returns an object that can be
+ used to adjust the other attributes of the method. The \a signature
+ and \a returnType will be normalized before they are added to
+ the class. If \a returnType is empty, then it indicates that
+ the method has \c{void} as its return type.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod
+ (const QByteArray& signature, const QByteArray& returnType)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Method, signature, returnType));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class that has the same information as
+ \a prototype. This is used to clone the methods of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the method.
+
+ This function will detect if \a prototype is an ordinary method,
+ signal, slot, or constructor and act accordingly.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
+{
+ QMetaMethodBuilder method;
+ if (prototype.methodType() == QMetaMethod::Method)
+ method = addMethod(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Signal)
+ method = addSignal(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Slot)
+ method = addSlot(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Constructor)
+ method = addConstructor(prototype.signature());
+ method.setReturnType(prototype.typeName());
+ method.setParameterNames(prototype.parameterNames());
+ method.setTag(prototype.tag());
+ method.setAccess(prototype.access());
+ method.setAttributes(prototype.attributes());
+ return method;
+}
+
+/*!
+ Adds a new public slot to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the slot. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSignal(), indexOfSlot()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new signal to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the signal. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSlot(), indexOfSignal()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Signal, signature, QByteArray(), QMetaMethod::Protected));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new constructor to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the constructor. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
+{
+ int index = d->constructors.size();
+ d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature));
+ return QMetaMethodBuilder(this, -(index + 1));
+}
+
+/*!
+ Adds a new constructor to this class that has the same information as
+ \a prototype. This is used to clone the constructors of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the constructor.
+
+ This function requires that \a prototype be a constructor.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
+{
+ Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
+ QMetaMethodBuilder ctor = addConstructor(prototype.signature());
+ ctor.setReturnType(prototype.typeName());
+ ctor.setParameterNames(prototype.parameterNames());
+ ctor.setTag(prototype.tag());
+ ctor.setAccess(prototype.access());
+ ctor.setAttributes(prototype.attributes());
+ return ctor;
+}
+
+/*!
+ Adds a new readable/writable property to this class with the specified
+ \a name and \a type. Returns an object that can be used to adjust
+ the other attributes of the property. The \a type will be
+ normalized before it is added to the class.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty
+ (const QByteArray& name, const QByteArray& type, int notifierId)
+{
+ int index = d->properties.size();
+ d->properties.append(QMetaPropertyBuilderPrivate(name, type, notifierId));
+ return QMetaPropertyBuilder(this, index);
+}
+
+/*!
+ Adds a new property to this class that has the same information as
+ \a prototype. This is used to clone the properties of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the property.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
+{
+ QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
+ property.setReadable(prototype.isReadable());
+ property.setWritable(prototype.isWritable());
+ property.setResettable(prototype.isResettable());
+ property.setDesignable(prototype.isDesignable());
+ property.setScriptable(prototype.isScriptable());
+ property.setStored(prototype.isStored());
+ property.setEditable(prototype.isEditable());
+ property.setUser(prototype.isUser());
+ property.setStdCppSet(prototype.hasStdCppSet());
+ property.setEnumOrFlag(prototype.isEnumType());
+ if (prototype.hasNotifySignal()) {
+ // Find an existing method for the notify signal, or add a new one.
+ QMetaMethod method = prototype.notifySignal();
+ int index = indexOfMethod(method.signature());
+ if (index == -1)
+ index = addMethod(method).index();
+ d->properties[property._index].notifySignal = index;
+ d->properties[property._index].setFlag(Notify, true);
+ }
+ return property;
+}
+
+/*!
+ Adds a new enumerator to this class with the specified
+ \a name. Returns an object that can be used to adjust
+ the other attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
+{
+ int index = d->enumerators.size();
+ d->enumerators.append(QMetaEnumBuilderPrivate(name));
+ return QMetaEnumBuilder(this, index);
+}
+
+/*!
+ Adds a new enumerator to this class that has the same information as
+ \a prototype. This is used to clone the enumerators of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
+{
+ QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setIsFlag(prototype.isFlag());
+ int count = prototype.keyCount();
+ for (int index = 0; index < count; ++index)
+ en.addKey(prototype.key(index), prototype.value(index));
+ return en;
+}
+
+/*!
+ Adds \a name and \a value as an item of class information to this class.
+ Returns the index of the new item of class information.
+
+ \sa classInfoCount(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
+{
+ int index = d->classInfoNames.size();
+ d->classInfoNames += name;
+ d->classInfoValues += value;
+ return index;
+}
+
+/*!
+ Adds \a meta to this class as a related meta object. Returns
+ the index of the new related meta object entry.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ int index = d->relatedMetaObjects.size();
+ d->relatedMetaObjects.append(meta);
+ return index;
+}
+
+/*!
+ Adds the contents of \a prototype to this meta object builder.
+ This function is useful for cloning the contents of an existing QMetaObject.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+*/
+void QMetaObjectBuilder::addMetaObject
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ Q_ASSERT(prototype);
+ int index;
+
+ if ((members & ClassName) != 0)
+ d->className = prototype->className();
+
+ if ((members & SuperClass) != 0)
+ d->superClass = prototype->superClass();
+
+ if ((members & (Methods | Signals | Slots)) != 0) {
+ for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
+ QMetaMethod method = prototype->method(index);
+ if (method.methodType() != QMetaMethod::Signal) {
+ if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
+ continue;
+ }
+ if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Signal &&
+ (members & Signals) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Slot &&
+ (members & Slots) != 0) {
+ addMethod(method);
+ }
+ }
+ }
+
+ if ((members & Constructors) != 0) {
+ for (index = 0; index < prototype->constructorCount(); ++index)
+ addConstructor(prototype->constructor(index));
+ }
+
+ if ((members & Properties) != 0) {
+ for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
+ addProperty(prototype->property(index));
+ }
+
+ if ((members & Enumerators) != 0) {
+ for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
+ addEnumerator(prototype->enumerator(index));
+ }
+
+ if ((members & ClassInfos) != 0) {
+ for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
+ QMetaClassInfo ci = prototype->classInfo(index);
+ addClassInfo(ci.name(), ci.value());
+ }
+ }
+
+ if ((members & RelatedMetaObjects) != 0) {
+ const QMetaObject **objects;
+ if (priv(prototype->d.data)->revision < 2) {
+ objects = (const QMetaObject **)(prototype->d.extradata);
+ } else {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra)
+ objects = extra->objects;
+ else
+ objects = 0;
+ }
+ if (objects) {
+ while (*objects != 0) {
+ addRelatedMetaObject(*objects);
+ ++objects;
+ }
+ }
+ }
+
+ if ((members & StaticMetacall) != 0) {
+ if (priv(prototype->d.data)->revision >= 2) {
+ const QMetaObjectExtraData *extra =
+ (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra && extra->static_metacall)
+ setStaticMetacallFunction(extra->static_metacall);
+ }
+ }
+}
+
+/*!
+ Returns the method at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
+{
+ if (index >= 0 && index < d->methods.size())
+ return QMetaMethodBuilder(this, index);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the constructor at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
+{
+ if (index >= 0 && index < d->constructors.size())
+ return QMetaMethodBuilder(this, -(index + 1));
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the property at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
+{
+ if (index >= 0 && index < d->properties.size())
+ return QMetaPropertyBuilder(this, index);
+ else
+ return QMetaPropertyBuilder();
+}
+
+/*!
+ Returns the enumerator at \a index in this class.
+
+ \sa enumeratorCount(), addEnumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
+{
+ if (index >= 0 && index < d->enumerators.size())
+ return QMetaEnumBuilder(this, index);
+ else
+ return QMetaEnumBuilder();
+}
+
+/*!
+ Returns the related meta object at \a index in this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ return d->relatedMetaObjects[index];
+ else
+ return 0;
+}
+
+/*!
+ Returns the name of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoName(int index) const
+{
+ if (index >= 0 && index < d->classInfoNames.size())
+ return d->classInfoNames[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoValue(int index) const
+{
+ if (index >= 0 && index < d->classInfoValues.size())
+ return d->classInfoValues[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Removes the method at \a index from this class. The indices of
+ all following methods will be adjusted downwards by 1. If the
+ method is registered as a notify signal on a property, then the
+ notify signal will be removed from the property.
+
+ \sa methodCount(), addMethod(), method(), indexOfMethod()
+*/
+void QMetaObjectBuilder::removeMethod(int index)
+{
+ if (index >= 0 && index < d->methods.size()) {
+ d->methods.removeAt(index);
+ for (int prop = 0; prop < d->properties.size(); ++prop) {
+ // Adjust the indices of property notify signal references.
+ if (d->properties[prop].notifySignal == index)
+ d->properties[prop].notifySignal = -1;
+ else if (d->properties[prop].notifySignal > index)
+ (d->properties[prop].notifySignal)--;
+ }
+ }
+}
+
+/*!
+ Removes the constructor at \a index from this class. The indices of
+ all following constructors will be adjusted downwards by 1.
+
+ \sa constructorCount(), addConstructor(), constructor()
+ \sa indexOfConstructor()
+*/
+void QMetaObjectBuilder::removeConstructor(int index)
+{
+ if (index >= 0 && index < d->constructors.size())
+ d->constructors.removeAt(index);
+}
+
+/*!
+ Removes the property at \a index from this class. The indices of
+ all following properties will be adjusted downwards by 1.
+
+ \sa propertyCount(), addProperty(), property(), indexOfProperty()
+*/
+void QMetaObjectBuilder::removeProperty(int index)
+{
+ if (index >= 0 && index < d->properties.size())
+ d->properties.removeAt(index);
+}
+
+/*!
+ Removes the enumerator at \a index from this class. The indices of
+ all following enumerators will be adjusted downwards by 1.
+
+ \sa enumertorCount(), addEnumerator(), enumerator()
+ \sa indexOfEnumerator()
+*/
+void QMetaObjectBuilder::removeEnumerator(int index)
+{
+ if (index >= 0 && index < d->enumerators.size())
+ d->enumerators.removeAt(index);
+}
+
+/*!
+ Removes the item of class information at \a index from this class.
+ The indices of all following items will be adjusted downwards by 1.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), classInfoValue()
+ \sa indexOfClassInfo()
+*/
+void QMetaObjectBuilder::removeClassInfo(int index)
+{
+ if (index >= 0 && index < d->classInfoNames.size()) {
+ d->classInfoNames.removeAt(index);
+ d->classInfoValues.removeAt(index);
+ }
+}
+
+/*!
+ Removes the related meta object at \a index from this class.
+ The indices of all following related meta objects will be adjusted
+ downwards by 1.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa relatedMetaObject()
+*/
+void QMetaObjectBuilder::removeRelatedMetaObject(int index)
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ d->relatedMetaObjects.removeAt(index);
+}
+
+/*!
+ Finds a method with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa method(), methodCount(), addMethod(), removeMethod()
+*/
+int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a signal with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSlot()
+*/
+int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Signal)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a slot with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSignal()
+*/
+int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Slot)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a constructor with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa constructor(), constructorCount(), addConstructor(), removeConstructor()
+*/
+int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->constructors.size(); ++index) {
+ if (sig == d->constructors[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a property with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa property(), propertyCount(), addProperty(), removeProperty()
+*/
+int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
+{
+ for (int index = 0; index < d->properties.size(); ++index) {
+ if (name == d->properties[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an enumerator with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa enumertor(), enumeratorCount(), addEnumerator(), removeEnumerator()
+*/
+int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
+{
+ for (int index = 0; index < d->enumerators.size(); ++index) {
+ if (name == d->enumerators[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an item of class information with the specified \a name and
+ returns its index; otherwise returns -1.
+
+ \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
+ \sa removeClassInfo()
+*/
+int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
+{
+ for (int index = 0; index < d->classInfoNames.size(); ++index) {
+ if (name == d->classInfoNames[index])
+ return index;
+ }
+ return -1;
+}
+
+// Align on a specific type boundary.
+#define ALIGN(size,type) \
+ (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
+
+// Build a string into a QMetaObject representation. Returns the
+// position in the string table where the string was placed.
+static int buildString
+ (char *buf, char *str, int *offset, const QByteArray& value, int empty)
+{
+ if (value.size() == 0 && empty >= 0)
+ return empty;
+ if (buf) {
+ memcpy(str + *offset, value.constData(), value.size());
+ str[*offset + value.size()] = '\0';
+ }
+ int posn = *offset;
+ *offset += value.size() + 1;
+ return posn;
+}
+
+// Build the parameter array string for a method.
+static QByteArray buildParameterNames
+ (const QByteArray& signature, const QList<QByteArray>& parameterNames)
+{
+ // If the parameter name list is specified, then concatenate them.
+ if (!parameterNames.isEmpty()) {
+ QByteArray names;
+ bool first = true;
+ foreach (QByteArray name, parameterNames) {
+ if (first)
+ first = false;
+ else
+ names += (char)',';
+ names += name;
+ }
+ return names;
+ }
+
+ // Count commas in the signature, excluding those inside template arguments.
+ int index = signature.indexOf('(');
+ if (index < 0)
+ return QByteArray();
+ ++index;
+ if (index >= signature.size())
+ return QByteArray();
+ if (signature[index] == ')')
+ return QByteArray();
+ int count = 1;
+ int brackets = 0;
+ while (index < signature.size() && signature[index] != ',') {
+ char ch = signature[index++];
+ if (ch == '<')
+ ++brackets;
+ else if (ch == '>')
+ --brackets;
+ else if (ch == ',' && brackets <= 0)
+ ++count;
+ }
+ return QByteArray(count - 1, ',');
+}
+
+// Build a QMetaObject in "buf" based on the information in "d".
+// If "buf" is null, then return the number of bytes needed to
+// build the QMetaObject.
+static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
+{
+ int size = 0;
+ int dataIndex;
+ int enumIndex;
+ int index;
+ bool hasNotifySignals = false;
+
+ // Create the main QMetaObject structure at the start of the buffer.
+ QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
+ size += sizeof(QMetaObject);
+ ALIGN(size, int);
+ if (buf) {
+ meta->d.superdata = d->superClass;
+ meta->d.extradata = 0;
+ }
+
+ // Populate the QMetaObjectPrivate structure.
+ QMetaObjectPrivate *pmeta
+ = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
+ dataIndex = 12; // Number of fields in the QMetaObjectPrivate.
+ for (index = 0; index < d->properties.size(); ++index) {
+ if (d->properties[index].notifySignal != -1) {
+ hasNotifySignals = true;
+ break;
+ }
+ }
+ if (buf) {
+ pmeta->revision = 2;
+ pmeta->className = 0; // Class name is always the first string.
+
+ pmeta->classInfoCount = d->classInfoNames.size();
+ pmeta->classInfoData = dataIndex;
+ dataIndex += 2 * d->classInfoNames.size();
+
+ pmeta->methodCount = d->methods.size();
+ pmeta->methodData = dataIndex;
+ dataIndex += 5 * d->methods.size();
+
+ pmeta->propertyCount = d->properties.size();
+ pmeta->propertyData = dataIndex;
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+
+ pmeta->enumeratorCount = d->enumerators.size();
+ pmeta->enumeratorData = dataIndex;
+ dataIndex += 4 * d->enumerators.size();
+
+ pmeta->constructorCount = d->constructors.size();
+ pmeta->constructorData = dataIndex;
+ dataIndex += 5 * d->constructors.size();
+ } else {
+ dataIndex += 2 * d->classInfoNames.size();
+ dataIndex += 5 * d->methods.size();
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+ dataIndex += 4 * d->enumerators.size();
+ dataIndex += 5 * d->constructors.size();
+ }
+
+ // Allocate space for the enumerator key names and values.
+ enumIndex = dataIndex;
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ dataIndex += 2 * enumerator->keys.size();
+ }
+
+ // Zero terminator at the end of the data offset table.
+ ++dataIndex;
+
+ // Find the start of the data and string tables.
+ int *data = reinterpret_cast<int *>(pmeta);
+ size += dataIndex * sizeof(int);
+ char *str = reinterpret_cast<char *>(buf + size);
+ if (buf) {
+ meta->d.stringdata = str;
+ meta->d.data = reinterpret_cast<uint *>(data);
+ }
+
+ // Reset the current data position to just past the QMetaObjectPrivate.
+ dataIndex = 12;
+
+ // Add the class name to the string table.
+ int offset = 0;
+ buildString(buf, str, &offset, d->className, -1);
+
+ // Add a common empty string, which is used to indicate "void"
+ // method returns, empty tag strings, etc.
+ int empty = buildString(buf, str, &offset, QByteArray(), -1);
+
+ // Output the class infos,
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ int name = buildString(buf, str, &offset, d->classInfoNames[index], empty);
+ int value = buildString(buf, str, &offset, d->classInfoValues[index], empty);
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = value;
+ }
+ dataIndex += 2;
+ }
+
+ // Output the methods in the class.
+ for (index = 0; index < d->methods.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // Output the properties in the class.
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ int name = buildString(buf, str, &offset, prop->name, empty);
+ int type = buildString(buf, str, &offset, prop->type, empty);
+ int flags = prop->flags;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = type;
+ data[dataIndex + 2] = flags;
+ }
+ dataIndex += 3;
+ }
+ if (hasNotifySignals) {
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ if (buf) {
+ if (prop->notifySignal != -1)
+ data[dataIndex] = prop->notifySignal;
+ else
+ data[dataIndex] = 0;
+ }
+ ++dataIndex;
+ }
+ }
+
+ // Output the enumerators in the class.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ int name = buildString(buf, str, &offset, enumerator->name, empty);
+ int isFlag = (int)(enumerator->isFlag);
+ int count = enumerator->keys.size();
+ int enumOffset = enumIndex;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = isFlag;
+ data[dataIndex + 2] = count;
+ data[dataIndex + 3] = enumOffset;
+ }
+ for (int key = 0; key < count; ++key) {
+ int keyIndex = buildString(buf, str, &offset, enumerator->keys[key], empty);
+ if (buf) {
+ data[enumOffset++] = keyIndex;
+ data[enumOffset++] = enumerator->values[key];
+ }
+ }
+ dataIndex += 4;
+ enumIndex += 2 * count;
+ }
+
+ // Output the constructors in the class.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // One more empty string to act as a terminator.
+ buildString(buf, str, &offset, QByteArray(), -1);
+ size += offset;
+
+ // Output the zero terminator in the data array.
+ if (buf)
+ data[enumIndex] = 0;
+
+ // Create the extradata block if we need one.
+ if (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction) {
+ ALIGN(size, QMetaObject **);
+ ALIGN(size, QMetaObjectBuilder::StaticMetacallFunction);
+ QMetaObjectExtraData *extra =
+ reinterpret_cast<QMetaObjectExtraData *>(buf + size);
+ size += sizeof(QMetaObjectExtraData);
+ ALIGN(size, QMetaObject *);
+ const QMetaObject **objects =
+ reinterpret_cast<const QMetaObject **>(buf + size);
+ if (buf) {
+ if (d->relatedMetaObjects.size() > 0) {
+ extra->objects = objects;
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index)
+ objects[index] = d->relatedMetaObjects[index];
+ objects[index] = 0;
+ } else {
+ extra->objects = 0;
+ }
+ extra->static_metacall = d->staticMetacallFunction;
+ meta->d.extradata = reinterpret_cast<void *>(extra);
+ }
+ if (d->relatedMetaObjects.size() > 0)
+ size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1);
+ }
+
+ // Align the final size and return it.
+ ALIGN(size, void *);
+ return size;
+}
+
+/*!
+ Converts this meta object builder into a concrete QMetaObject.
+ The return value should be deallocated using qFree() once it
+ is no longer needed.
+
+ The returned meta object is a snapshot of the state of the
+ QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
+ will not be reflected in previous meta objects returned by
+ this method.
+*/
+QMetaObject *QMetaObjectBuilder::toMetaObject() const
+{
+ int size = buildMetaObject(d, 0);
+ char *buf = reinterpret_cast<char *>(qMalloc(size));
+ buildMetaObject(d, buf);
+ return reinterpret_cast<QMetaObject *>(buf);
+}
+
+/*!
+ \typedef QMetaObjectBuilder::StaticMetacallFunction
+
+ Typedef for static metacall functions. The three parameters are
+ the call type value, the constructor index, and the
+ array of parameters.
+*/
+
+/*!
+ Returns the static metacall function to use to construct objects
+ of this class. The default value is null.
+
+ \sa setStaticMetacallFunction()
+*/
+QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
+{
+ return d->staticMetacallFunction;
+}
+
+/*!
+ Sets the static metacall function to use to construct objects
+ of this class to \a value. The default value is null.
+
+ \sa staticMetacallFunction()
+*/
+void QMetaObjectBuilder::setStaticMetacallFunction
+ (QMetaObjectBuilder::StaticMetacallFunction value)
+{
+ d->staticMetacallFunction = value;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ Serializes the contents of the meta object builder onto \a stream.
+
+ \sa deserialize()
+*/
+void QMetaObjectBuilder::serialize(QDataStream& stream) const
+{
+ int index;
+
+ // Write the class and super class names.
+ stream << d->className;
+ if (d->superClass)
+ stream << QByteArray(d->superClass->className());
+ else
+ stream << QByteArray();
+
+ // Write the counts for each type of class member.
+ stream << d->classInfoNames.size();
+ stream << d->methods.size();
+ stream << d->properties.size();
+ stream << d->enumerators.size();
+ stream << d->constructors.size();
+ stream << d->relatedMetaObjects.size();
+
+ // Write the items of class information.
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ stream << d->classInfoNames[index];
+ stream << d->classInfoValues[index];
+ }
+
+ // Write the methods.
+ for (index = 0; index < d->methods.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the properties.
+ for (index = 0; index < d->properties.size(); ++index) {
+ const QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream << property->name;
+ stream << property->type;
+ stream << property->flags;
+ stream << property->notifySignal;
+ }
+
+ // Write the enumerators.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ const QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream << enumerator->name;
+ stream << enumerator->isFlag;
+ stream << enumerator->keys;
+ stream << enumerator->values;
+ }
+
+ // Write the constructors.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the related meta objects.
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
+ const QMetaObject *meta = d->relatedMetaObjects[index];
+ stream << QByteArray(meta->className());
+ }
+
+ // Add an extra empty QByteArray for additional data in future versions.
+ // This should help maintain backwards compatibility, allowing older
+ // versions to read newer data.
+ stream << QByteArray();
+}
+
+// Resolve a class name using the name reference map.
+static const QMetaObject *resolveClassName
+ (const QMap<QByteArray, const QMetaObject *>& references,
+ const QByteArray& name)
+{
+ if (name == QByteArray("QObject"))
+ return &QObject::staticMetaObject;
+ else
+ return references.value(name, 0);
+}
+
+/*!
+ Deserializes a meta object builder from \a stream into
+ this meta object builder.
+
+ The \a references parameter specifies a mapping from class names
+ to QMetaObject instances for resolving the super class name and
+ related meta objects in the object that is deserialized.
+ The meta object for QObject is implicitly added to \a references
+ and does not need to be supplied.
+
+ The QDataStream::status() value on \a stream will be set to
+ QDataStream::ReadCorruptData if the input data is corrupt.
+ The status will be set to QDataStream::ReadPastEnd if the
+ input was exhausted before the full meta object was read.
+
+ \sa serialize()
+*/
+void QMetaObjectBuilder::deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references)
+{
+ QByteArray name;
+ const QMetaObject *cl;
+ int index;
+
+ // Clear all members in the builder to their default states.
+ d->className.clear();
+ d->superClass = &QObject::staticMetaObject;
+ d->classInfoNames.clear();
+ d->classInfoValues.clear();
+ d->methods.clear();
+ d->properties.clear();
+ d->enumerators.clear();
+ d->constructors.clear();
+ d->relatedMetaObjects.clear();
+ d->staticMetacallFunction = 0;
+
+ // Read the class and super class names.
+ stream >> d->className;
+ stream >> name;
+ if (name.isEmpty()) {
+ d->superClass = 0;
+ } else if ((cl = resolveClassName(references, name)) != 0) {
+ d->superClass = cl;
+ } else {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the counts for each type of class member.
+ int classInfoCount, methodCount, propertyCount;
+ int enumeratorCount, constructorCount, relatedMetaObjectCount;
+ stream >> classInfoCount;
+ stream >> methodCount;
+ stream >> propertyCount;
+ stream >> enumeratorCount;
+ stream >> constructorCount;
+ stream >> relatedMetaObjectCount;
+ if (classInfoCount < 0 || methodCount < 0 ||
+ propertyCount < 0 || enumeratorCount < 0 ||
+ constructorCount < 0 || relatedMetaObjectCount < 0) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the items of class information.
+ for (index = 0; index < classInfoCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray value;
+ stream >> name;
+ stream >> value;
+ addClassInfo(name, value);
+ }
+
+ // Read the member methods.
+ for (index = 0; index < methodCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addMethod(name);
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() == QMetaMethod::Constructor) {
+ // Cannot add a constructor in this set of methods.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the properties.
+ for (index = 0; index < propertyCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray type;
+ stream >> name;
+ stream >> type;
+ addProperty(name, type);
+ QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream >> property->flags;
+ stream >> property->notifySignal;
+ if (property->notifySignal < -1 ||
+ property->notifySignal >= d->methods.size()) {
+ // Notify signal method index is out of range.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ if (property->notifySignal >= 0 &&
+ d->methods[property->notifySignal].methodType() != QMetaMethod::Signal) {
+ // Notify signal method index does not refer to a signal.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the enumerators.
+ for (index = 0; index < enumeratorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addEnumerator(name);
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream >> enumerator->isFlag;
+ stream >> enumerator->keys;
+ stream >> enumerator->values;
+ if (enumerator->keys.size() != enumerator->values.size()) {
+ // Mismatch between number of keys and number of values.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the constructor methods.
+ for (index = 0; index < constructorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addConstructor(name);
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() != QMetaMethod::Constructor) {
+ // The type must be Constructor.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the related meta objects.
+ for (index = 0; index < relatedMetaObjectCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ cl = resolveClassName(references, name);
+ if (!cl) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ addRelatedMetaObject(cl);
+ }
+
+ // Read the extra data block, which is reserved for future use.
+ stream >> name;
+}
+
+#endif // !QT_NO_DATASTREAM
+
+/*!
+ \class QMetaMethodBuilder
+ \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
+*/
+
+QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
+{
+ // Positive indices indicate methods, negative indices indicate constructors.
+ if (_mobj && _index >= 0 && _index < _mobj->d->methods.size())
+ return &(_mobj->d->methods[_index]);
+ else if (_mobj && -_index >= 1 && -_index <= _mobj->d->constructors.size())
+ return &(_mobj->d->constructors[(-_index) - 1]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaMethodBuilder::QMetaMethodBuilder()
+ \internal
+*/
+
+/*!
+ Returns the index of this method within its QMetaObjectBuilder.
+*/
+int QMetaMethodBuilder::index() const
+{
+ if (_index >= 0)
+ return _index; // Method, signal, or slot
+ else
+ return (-_index) - 1; // Constructor
+}
+
+/*!
+ Returns the type of this method (signal, slot, method, or constructor).
+*/
+QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->methodType();
+ else
+ return QMetaMethod::Method;
+}
+
+/*!
+ Returns the signature of this method.
+
+ \sa parameterNames(), returnType()
+*/
+QByteArray QMetaMethodBuilder::signature() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->signature;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the return type for this method; empty if the method's
+ return type is \c{void}.
+
+ \sa setReturnType(), signature()
+*/
+QByteArray QMetaMethodBuilder::returnType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->returnType;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the return type for this method to \a value. If \a value
+ is empty, then the method's return type is \c{void}. The \a value
+ will be normalized before it is added to the method.
+
+ \sa returnType(), signature()
+*/
+void QMetaMethodBuilder::setReturnType(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->returnType = QMetaObject::normalizedType(value);
+}
+
+/*!
+ Returns the list of parameter names for this method.
+
+ \sa setParameterNames()
+*/
+QList<QByteArray> QMetaMethodBuilder::parameterNames() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->parameterNames;
+ else
+ return QList<QByteArray>();
+}
+
+/*!
+ Sets the list of parameter names for this method to \a value.
+
+ \sa parameterNames()
+*/
+void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->parameterNames = value;
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ \sa setTag()
+*/
+QByteArray QMetaMethodBuilder::tag() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->tag;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the tag associated with this method to \a value.
+
+ \sa setTag()
+*/
+void QMetaMethodBuilder::setTag(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->tag = value;
+}
+
+/*!
+ Returns the access specification of this method (private, protected,
+ or public). The default value is QMetaMethod::Public for methods,
+ slots, and constructors. The default value is QMetaMethod::Protected
+ for signals.
+
+ \sa setAccess()
+*/
+QMetaMethod::Access QMetaMethodBuilder::access() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->access();
+ else
+ return QMetaMethod::Public;
+}
+
+/*!
+ Sets the access specification of this method (private, protected,
+ or public) to \a value. If the method is a signal, this function
+ will be ignored.
+
+ \sa access()
+*/
+void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d && d->methodType() != QMetaMethod::Signal)
+ d->setAccess(value);
+}
+
+/*!
+ Returns the additional attributes for this method.
+
+ \sa setAttributes()
+*/
+int QMetaMethodBuilder::attributes() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return (d->attributes >> 4);
+ else
+ return 0;
+}
+
+/*!
+ Sets the additional attributes for this method to \a value.
+
+ \sa attributes()
+*/
+void QMetaMethodBuilder::setAttributes(int value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->attributes = ((d->attributes & 0x0f) | (value << 4));
+}
+
+/*!
+ \class QMetaPropertyBuilder
+ \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
+*/
+
+QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->properties.size())
+ return &(_mobj->d->properties[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaPropertyBuilder::index() const
+
+ Returns the index of this property within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name associated with this property.
+
+ \sa type()
+*/
+QByteArray QMetaPropertyBuilder::name() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the type associated with this property.
+
+ \sa name()
+*/
+QByteArray QMetaPropertyBuilder::type() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->type;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this property has a notify signal; false otherwise.
+
+ \sa notifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+bool QMetaPropertyBuilder::hasNotifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Notify);
+ else
+ return false;
+}
+
+/*!
+ Returns the notify signal associated with this property.
+
+ \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d && d->notifySignal >= 0)
+ return QMetaMethodBuilder(_mobj, d->notifySignal);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Sets the notify signal associated with this property to \a value.
+
+ \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
+*/
+void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ if (value._mobj) {
+ d->notifySignal = value._index;
+ d->setFlag(Notify, true);
+ } else {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+ }
+}
+
+/*!
+ Removes the notify signal from this property.
+
+ \sa hasNotifySignal(), notifySignal(), setNotifySignal()
+*/
+void QMetaPropertyBuilder::removeNotifySignal()
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+ The default value is true.
+
+ \sa setReadable(), isWritable()
+*/
+bool QMetaPropertyBuilder::isReadable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Readable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns false.
+ The default value is true.
+
+ \sa setWritable(), isReadable()
+*/
+bool QMetaPropertyBuilder::isWritable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Writable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false. The default value is false.
+
+ \sa setResettable()
+*/
+bool QMetaPropertyBuilder::isResettable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Resettable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designable; otherwise returns false.
+ This default value is false.
+
+ \sa setDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isDesignable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Designable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is scriptable; otherwise returns false.
+ This default value is false.
+
+ \sa setScriptable(), isDesignable(), isStored()
+*/
+bool QMetaPropertyBuilder::isScriptable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Scriptable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is stored; otherwise returns false.
+ This default value is false.
+
+ \sa setStored(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isStored() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Stored);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is editable; otherwise returns false.
+ This default value is false.
+
+ \sa setEditable(), isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isEditable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Editable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit or that is
+ significant in some other way. Otherwise it returns
+ false. This default value is false.
+
+ \sa setUser(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isUser() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(User);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern. The default value is false.
+
+ \sa setStdCppSet()
+*/
+bool QMetaPropertyBuilder::hasStdCppSet() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(StdCppSet);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is an enumerator or flag type;
+ otherwise returns false. This default value is false.
+
+ \sa setEnumOrFlag()
+*/
+bool QMetaPropertyBuilder::isEnumOrFlag() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(EnumOrFlag);
+ else
+ return false;
+}
+
+/*!
+ Sets this property to readable if \a value is true.
+
+ \sa isReadable(), setWritable()
+*/
+void QMetaPropertyBuilder::setReadable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Readable, value);
+}
+
+/*!
+ Sets this property to writable if \a value is true.
+
+ \sa isWritable(), setReadable()
+*/
+void QMetaPropertyBuilder::setWritable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Writable, value);
+}
+
+/*!
+ Sets this property to resettable if \a value is true.
+
+ \sa isResettable()
+*/
+void QMetaPropertyBuilder::setResettable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Resettable, value);
+}
+
+/*!
+ Sets this property to designable if \a value is true.
+
+ \sa isDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setDesignable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Designable, value);
+}
+
+/*!
+ Sets this property to scriptable if \a value is true.
+
+ \sa isScriptable(), setDesignable(), setStored()
+*/
+void QMetaPropertyBuilder::setScriptable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Scriptable, value);
+}
+
+/*!
+ Sets this property to storable if \a value is true.
+
+ \sa isStored(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setStored(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Stored, value);
+}
+
+/*!
+ Sets this property to editable if \a value is true.
+
+ \sa isEditable(), setDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setEditable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Editable, value);
+}
+
+/*!
+ Sets the \c USER flag on this property to \a value.
+
+ \sa isUser(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setUser(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(User, value);
+}
+
+/*!
+ Sets the C++ setter flag on this property to \a value, which is
+ true if the property has a C++ setter function that follows Qt's
+ standard "name" / "setName" pattern.
+
+ \sa hasStdCppSet()
+*/
+void QMetaPropertyBuilder::setStdCppSet(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(StdCppSet, value);
+}
+
+/*!
+ Sets this property to be of an enumerator or flag type if
+ \a value is true.
+
+ \sa isEnumOrFlag()
+*/
+void QMetaPropertyBuilder::setEnumOrFlag(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(EnumOrFlag, value);
+}
+
+/*!
+ \class QMetaEnumBuilder
+ \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
+*/
+
+QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->enumerators.size())
+ return &(_mobj->d->enumerators[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaEnumBuilder::QMetaEnumBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaEnumBuilder::index() const
+
+ Returns the index of this enumerator within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+*/
+QByteArray QMetaEnumBuilder::name() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ \sa setIsFlag()
+*/
+bool QMetaEnumBuilder::isFlag() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->isFlag;
+ else
+ return false;
+}
+
+/*!
+ Sets this enumerator to be used as a flag if \a value is true.
+
+ \sa isFlag()
+*/
+void QMetaEnumBuilder::setIsFlag(bool value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->isFlag = value;
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key(), addKey()
+*/
+int QMetaEnumBuilder::keyCount() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->keys.size();
+ else
+ return 0;
+}
+
+/*!
+ Returns the key with the given \a index, or an empty QByteArray
+ if no such key exists.
+
+ \sa keyCount(), addKey(), value()
+*/
+QByteArray QMetaEnumBuilder::key(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->keys[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), addKey(), key()
+*/
+int QMetaEnumBuilder::value(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->values[index];
+ else
+ return -1;
+}
+
+/*!
+ Adds a new key called \a name to this enumerator, associated
+ with \a value. Returns the index of the new key.
+
+ \sa keyCount(), key(), value(), removeKey()
+*/
+int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d) {
+ int index = d->keys.size();
+ d->keys += name;
+ d->values += value;
+ return index;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Removes the key at \a index from this enumerator.
+
+ \sa addKey()
+*/
+void QMetaEnumBuilder::removeKey(int index)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size()) {
+ d->keys.removeAt(index);
+ d->values.removeAt(index);
+ }
+}
diff --git a/tests/auto/dynamicobject/qmetaobjectbuilder.h b/tests/auto/dynamicobject/qmetaobjectbuilder.h
new file mode 100644
index 0000000..d820860
--- /dev/null
+++ b/tests/auto/dynamicobject/qmetaobjectbuilder.h
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECTBUILDER_H
+#define QMETAOBJECTBUILDER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmap.h>
+
+class QMetaObjectBuilderPrivate;
+class QMetaMethodBuilder;
+class QMetaMethodBuilderPrivate;
+class QMetaPropertyBuilder;
+class QMetaPropertyBuilderPrivate;
+class QMetaEnumBuilder;
+class QMetaEnumBuilderPrivate;
+
+class QMetaObjectBuilder
+{
+public:
+ enum AddMember
+ {
+ ClassName = 0x00000001,
+ SuperClass = 0x00000002,
+ Methods = 0x00000004,
+ Signals = 0x00000008,
+ Slots = 0x00000010,
+ Constructors = 0x00000020,
+ Properties = 0x00000040,
+ Enumerators = 0x00000080,
+ ClassInfos = 0x00000100,
+ RelatedMetaObjects = 0x00000200,
+ StaticMetacall = 0x00000400,
+ PublicMethods = 0x00000800,
+ ProtectedMethods = 0x00001000,
+ PrivateMethods = 0x00002000,
+ AllMembers = 0x7FFFFFFF,
+ AllPrimaryMembers = 0x7FFFFBFC
+ };
+ Q_DECLARE_FLAGS(AddMembers, AddMember)
+
+ QMetaObjectBuilder();
+ explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+ virtual ~QMetaObjectBuilder();
+
+ QByteArray className() const;
+ void setClassName(const QByteArray& name);
+
+ const QMetaObject *superClass() const;
+ void setSuperClass(const QMetaObject *meta);
+
+ int methodCount() const;
+ int constructorCount() const;
+ int propertyCount() const;
+ int enumeratorCount() const;
+ int classInfoCount() const;
+ int relatedMetaObjectCount() const;
+
+ QMetaMethodBuilder addMethod(const QByteArray& signature);
+ QMetaMethodBuilder addMethod(const QByteArray& signature, const QByteArray& returnType);
+ QMetaMethodBuilder addMethod(const QMetaMethod& prototype);
+
+ QMetaMethodBuilder addSlot(const QByteArray& signature);
+ QMetaMethodBuilder addSignal(const QByteArray& signature);
+
+ QMetaMethodBuilder addConstructor(const QByteArray& signature);
+ QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
+
+ QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
+ QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
+
+ QMetaEnumBuilder addEnumerator(const QByteArray& name);
+ QMetaEnumBuilder addEnumerator(const QMetaEnum& prototype);
+
+ int addClassInfo(const QByteArray& name, const QByteArray& value);
+
+ int addRelatedMetaObject(const QMetaObject *meta);
+
+ void addMetaObject(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+
+ QMetaMethodBuilder method(int index) const;
+ QMetaMethodBuilder constructor(int index) const;
+ QMetaPropertyBuilder property(int index) const;
+ QMetaEnumBuilder enumerator(int index) const;
+ const QMetaObject *relatedMetaObject(int index) const;
+
+ QByteArray classInfoName(int index) const;
+ QByteArray classInfoValue(int index) const;
+
+ void removeMethod(int index);
+ void removeConstructor(int index);
+ void removeProperty(int index);
+ void removeEnumerator(int index);
+ void removeClassInfo(int index);
+ void removeRelatedMetaObject(int index);
+
+ int indexOfMethod(const QByteArray& signature);
+ int indexOfSignal(const QByteArray& signature);
+ int indexOfSlot(const QByteArray& signature);
+ int indexOfConstructor(const QByteArray& signature);
+ int indexOfProperty(const QByteArray& name);
+ int indexOfEnumerator(const QByteArray& name);
+ int indexOfClassInfo(const QByteArray& name);
+
+ typedef int (*StaticMetacallFunction)(QMetaObject::Call, int, void **);
+
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const;
+ void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
+
+ QMetaObject *toMetaObject() const;
+
+#ifndef QT_NO_DATASTREAM
+ void serialize(QDataStream& stream) const;
+ void deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references);
+#endif
+
+private:
+ Q_DISABLE_COPY(QMetaObjectBuilder);
+
+ QMetaObjectBuilderPrivate *d;
+
+ friend class QMetaMethodBuilder;
+ friend class QMetaPropertyBuilder;
+ friend class QMetaEnumBuilder;
+};
+
+class QMetaMethodBuilder
+{
+public:
+ QMetaMethodBuilder() : _mobj(0), _index(0) {}
+
+ int index() const;
+
+ QMetaMethod::MethodType methodType() const;
+ QByteArray signature() const;
+
+ QByteArray returnType() const;
+ void setReturnType(const QByteArray& value);
+
+ QList<QByteArray> parameterNames() const;
+ void setParameterNames(const QList<QByteArray>& value);
+
+ QByteArray tag() const;
+ void setTag(const QByteArray& value);
+
+ QMetaMethod::Access access() const;
+ void setAccess(QMetaMethod::Access value);
+
+ int attributes() const;
+ void setAttributes(int value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+ friend class QMetaPropertyBuilder;
+
+ QMetaMethodBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaMethodBuilderPrivate *d_func() const;
+};
+
+class QMetaPropertyBuilder
+{
+public:
+ QMetaPropertyBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+ QByteArray type() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethodBuilder notifySignal() const;
+ void setNotifySignal(const QMetaMethodBuilder& value);
+ void removeNotifySignal();
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable() const;
+ bool isScriptable() const;
+ bool isStored() const;
+ bool isEditable() const;
+ bool isUser() const;
+ bool hasStdCppSet() const;
+ bool isEnumOrFlag() const;
+
+ void setReadable(bool value);
+ void setWritable(bool value);
+ void setResettable(bool value);
+ void setDesignable(bool value);
+ void setScriptable(bool value);
+ void setStored(bool value);
+ void setEditable(bool value);
+ void setUser(bool value);
+ void setStdCppSet(bool value);
+ void setEnumOrFlag(bool value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaPropertyBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaPropertyBuilderPrivate *d_func() const;
+};
+
+class QMetaEnumBuilder
+{
+public:
+ QMetaEnumBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+
+ bool isFlag() const;
+ void setIsFlag(bool value);
+
+ int keyCount() const;
+ QByteArray key(int index) const;
+ int value(int index) const;
+
+ int addKey(const QByteArray& name, int value);
+ void removeKey(int index);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaEnumBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaEnumBuilderPrivate *d_func() const;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
+
+#endif
diff --git a/tests/auto/dynamicobject/tst_qobject.cpp b/tests/auto/dynamicobject/tst_qobject.cpp
new file mode 100644
index 0000000..18805f7
--- /dev/null
+++ b/tests/auto/dynamicobject/tst_qobject.cpp
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+****************************************************************************/
+
+#define QT3_SUPPORT
+#include <QtTest/QtTest>
+
+
+#include <qcoreapplication.h>
+
+#include <qmetaobject.h>
+
+#include "qobject.h"
+#include "private/qobject_p.h"
+#include "qmetaobjectbuilder.h"
+#include "qdynamicmetaobject.h"
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QObject();
+ virtual ~tst_QObject();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void addSignal();
+ void addSlot();
+ void addProperty();
+ void dynamicProperty();
+};
+
+//===========================================================================
+
+class MyDynamicMetaObject : public QDynamicMetaObject
+{
+public:
+ MyDynamicMetaObject(const QMetaObject *base);
+
+ int createProperty(const QObject *object, const char *, const char *);
+
+ virtual void callSlot(QObject *object, int id, const QList<QVariant> &args);
+
+ virtual void writeProperty(QObject *, int id, const QVariant &value) {
+ props[property(id).name()] = value;
+ }
+
+ virtual QVariant readProperty(QObject *, int id) const {
+ return props[property(id).name()];
+ }
+
+ QString calledSlot;
+ QString string;
+
+private:
+ QMap<QString,QVariant> props;
+};
+
+MyDynamicMetaObject::MyDynamicMetaObject(const QMetaObject *_base)
+ : QDynamicMetaObject(_base)
+{
+}
+
+void MyDynamicMetaObject::callSlot(QObject *object, int id, const QList<QVariant> &args)
+{
+ calledSlot = method(id).signature();
+ qDebug() << "Handled slot" << id << calledSlot << args;
+ if (calledSlot == "string(QString)") {
+ string = args[0].toString();
+ }
+}
+
+int MyDynamicMetaObject::createProperty(const QObject *, const char *name, const char *type)
+{
+ qDebug() << "createProperty" << name;
+ if (name == QString("dynamicProp")) {
+ addProperty(name, type);
+ int id = indexOfProperty(name);
+ return id;
+ }
+
+ return -1;
+}
+
+//===========================================================================
+
+class MyDynamicObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyDynamicObject();
+
+ void addSignal(const char *sigName) {
+ dynamicMeta->addSignal(sigName);
+ }
+
+ void addSignal(const char *sigName, const QList<QByteArray> &parameterNames) {
+ dynamicMeta->addSignal(sigName, parameterNames);
+ }
+
+ void emitSignal(const char *sigName) {
+ int idx = dynamicMeta->indexOfSignal(sigName);
+ if (idx >= 0)
+ dynamicMeta->activate(this, idx, 0);
+ }
+
+ void emitSignal(const char *sigName, QGenericArgument val0
+ , QGenericArgument val1=QGenericArgument(0)
+ , QGenericArgument val2=QGenericArgument(0)
+ , QGenericArgument val3=QGenericArgument(0)
+ , QGenericArgument val4=QGenericArgument(0)
+ , QGenericArgument val5=QGenericArgument(0)
+ , QGenericArgument val6=QGenericArgument(0)
+ , QGenericArgument val7=QGenericArgument(0))
+ {
+ int idx = dynamicMeta->indexOfSignal(sigName);
+ if (idx >= 0) {
+ QGenericReturnArgument rv;
+ dynamicMeta->method(idx).invoke(this, Qt::DirectConnection, rv,
+ val0, val1, val2, val3, val4, val5, val6, val7);
+ }
+ }
+
+ void addSlot(const char *slotName) {
+ dynamicMeta->addSlot(slotName);
+ }
+
+ void addSlot(const char *slotName, const QList<QByteArray> &parameterNames) {
+ dynamicMeta->addSlot(slotName, parameterNames);
+ }
+
+ void addProperty(const char *name, const char *type, const char *notifier) {
+ dynamicMeta->addProperty(name, type, notifier);
+ }
+
+ QString calledSlot() const { return dynamicMeta->calledSlot; }
+
+ void emitNormalSignal() { emit normalSignal(); }
+
+ MyDynamicMetaObject *dynamicMeta;
+
+public slots:
+ void normalSlot() {}
+
+signals:
+ void normalSignal();
+
+};
+
+MyDynamicObject::MyDynamicObject()
+ : QObject()
+{
+ dynamicMeta = new MyDynamicMetaObject(&staticMetaObject);
+ setDynamicMetaObject(dynamicMeta);
+}
+
+//===========================================================================
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+public:
+ TestObject() : slot1Called(false), slot2Called(false) {}
+
+ void emitSignal() { emit triggered(); }
+ void setText(const QString &str) { emit textChanged(str); }
+
+ bool slot1Called;
+ bool slot2Called;
+ QString string;
+
+public slots:
+ void slot1() {
+ slot1Called = true;
+ qDebug() << "Called slot1()";
+ }
+
+ void slot2() {
+ slot2Called = true;
+ qDebug() << "Called slot2()";
+ }
+
+ void slotString(QString str) {
+ string = str;
+ qDebug() << "Called slotString()" << str;
+ }
+
+signals:
+ void triggered();
+ void textChanged(QString);
+};
+
+
+tst_QObject::tst_QObject()
+{
+
+}
+
+tst_QObject::~tst_QObject()
+{
+
+}
+
+void tst_QObject::initTestCase()
+{
+}
+
+void tst_QObject::cleanupTestCase()
+{
+}
+
+void tst_QObject::init()
+{
+}
+
+void tst_QObject::cleanup()
+{
+}
+
+void tst_QObject::addSignal()
+{
+ MyDynamicObject myObj;
+ myObj.addSignal("testSignal()");
+
+ TestObject testObj;
+
+ connect(&myObj, SIGNAL(testSignal()), &testObj, SLOT(slot1()));
+ connect(&myObj, SIGNAL(normalSignal()), &testObj, SLOT(slot2()));
+
+ myObj.emitSignal("testSignal()");
+
+ QVERIFY(testObj.slot1Called);
+ QVERIFY(!testObj.slot2Called);
+
+ testObj.slot1Called = false;
+
+ myObj.emitNormalSignal();
+
+ QVERIFY(!testObj.slot1Called);
+ QVERIFY(testObj.slot2Called);
+
+ // With parameter
+ myObj.addSignal("stringSignal(QString)");
+ connect(&myObj, SIGNAL(stringSignal(QString)), &testObj, SLOT(slotString(QString)));
+
+ QString param("Hello");
+ myObj.emitSignal("stringSignal(QString)", Q_ARG(QString, param));
+
+ QCOMPARE(testObj.string, QString("Hello"));
+}
+
+void tst_QObject::addSlot()
+{
+ MyDynamicObject myObj;
+ myObj.addSlot("testSlot1()");
+ myObj.addSignal("testSignal()");
+ myObj.addSlot("testSlot()");
+
+ TestObject testObj;
+
+ connect(&testObj, SIGNAL(triggered()), &myObj, SLOT(testSlot()));
+ connect(&testObj, SIGNAL(triggered()), &myObj, SIGNAL(testSignal())); // signal chaining
+ connect(&myObj, SIGNAL(testSignal()), &testObj, SLOT(slot1()));
+
+ testObj.emitSignal();
+
+ QCOMPARE(myObj.calledSlot(), QString("testSlot()"));
+ QVERIFY(testObj.slot1Called);
+
+ // Verify parameter type and name
+ myObj.addSlot("string(QString)", QList<QByteArray>() << "name");
+ int idx = myObj.metaObject()->indexOfSlot("string(QString)");
+ QVERIFY(idx > 0);
+ QMetaMethod method = myObj.metaObject()->method(idx);
+ QVERIFY(method.parameterTypes()[0] == "QString");
+ QVERIFY(method.parameterNames()[0] == "name");
+
+ connect(&testObj, SIGNAL(textChanged(QString)), &myObj, SLOT(string(QString)));
+ testObj.setText("Hello");
+ QCOMPARE(myObj.dynamicMeta->string, QString("Hello"));
+}
+
+void tst_QObject::addProperty()
+{
+ MyDynamicObject myObj;
+ myObj.addSignal("propChanged()");
+ myObj.addProperty("myProp", QVariant::typeToName(QVariant::String), "propChanged()");
+
+ myObj.setProperty("myProp", QString("hello"));
+ qDebug() << "property value" << myObj.property("myProp").toString();
+ QCOMPARE(myObj.property("myProp").toString(), QString("hello"));
+
+ TestObject testObj;
+ connect(&myObj, SIGNAL(propChanged()), &testObj, SLOT(slot1()));
+ myObj.setProperty("myProp", QString("there"));
+
+ QCOMPARE(myObj.property("myProp").toString(), QString("there"));
+ QVERIFY(testObj.slot1Called);
+}
+
+void tst_QObject::dynamicProperty()
+{
+ MyDynamicObject myObj;
+
+ myObj.setProperty("dynamicProp", QString("hello"));
+ qDebug() << "property value" << myObj.property("dynamicProp").toString();
+ QCOMPARE(myObj.property("dynamicProp").toString(), QString("hello"));
+}
+
+QTEST_MAIN(tst_QObject)
+#include "tst_qobject.moc"
diff --git a/tests/auto/qmake/testdata/bundle-spaces/some-file b/tests/auto/qmake/testdata/bundle-spaces/some-file
index 9975dba..e69de29 100644
--- a/tests/auto/qmake/testdata/bundle-spaces/some-file
+++ b/tests/auto/qmake/testdata/bundle-spaces/some-file
@@ -1,6 +0,0 @@
-all:
- C:\git\qt-kinetic-animations\bin\qmake qdir.pro -o Makefile -spec win32-msvc2008
- nmake -f Makefile
-first: all
-qmake:
- C:\git\qt-kinetic-animations\bin\qmake qdir.pro -o Makefile -spec win32-msvc2008
diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro
index bc41125..70289e2 100644
--- a/tests/benchmarks/benchmarks.pro
+++ b/tests/benchmarks/benchmarks.pro
@@ -16,6 +16,14 @@ SUBDIRS = containers-associative \
qregion \
qvariant \
qwidget \
- qtwidgets
+ qtwidgets \
+ qmlxmlparser \
+ qfxview \
contains(QT_CONFIG, opengl): SUBDIRS += opengl
+
+# Tests which should run in Pulse
+PULSE_TESTS = \
+ qfxview \
+ qmlxmlparser \
+
diff --git a/tests/benchmarks/qmlpainting/qmlpainting.pro b/tests/benchmarks/qmlpainting/qmlpainting.pro
new file mode 100644
index 0000000..58e9775
--- /dev/null
+++ b/tests/benchmarks/qmlpainting/qmlpainting.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qmlpainting
+
+SOURCES += tst_qmlpainting.cpp
diff --git a/tests/benchmarks/qmlpainting/tst_qmlpainting.cpp b/tests/benchmarks/qmlpainting/tst_qmlpainting.cpp
new file mode 100644
index 0000000..ae6f9a3
--- /dev/null
+++ b/tests/benchmarks/qmlpainting/tst_qmlpainting.cpp
@@ -0,0 +1,696 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** 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 <qtest.h>
+#include <QPainter>
+#include <QImage>
+
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+class tst_QmlPainting : public QObject
+{
+ Q_OBJECT
+
+ public:
+ tst_QmlPainting() {}
+
+private slots:
+ void drawRoundedRect();
+ void drawScaledRoundedRect();
+ void drawTransformedRoundedRect();
+ void drawAntialiasedRoundedRect();
+ void drawScaledAntialiasedRoundedRect_data();
+ void drawScaledAntialiasedRoundedRect();
+ void drawTransformedAntialiasedRoundedRect_data();
+ void drawTransformedAntialiasedRoundedRect();
+ void drawImageRoundedRect();
+ void drawScaledImageRoundedRect_data();
+ void drawScaledImageRoundedRect();
+ void drawTransformedImageRoundedRect_data();
+ void drawTransformedImageRoundedRect();
+ void drawScaleGridRoundedRect();
+ void drawScaledScaleGridRoundedRect_data();
+ void drawScaledScaleGridRoundedRect();
+ void drawTransformedScaleGridRoundedRect_data();
+ void drawTransformedScaleGridRoundedRect();
+ void drawTransformedTransparentImage_data();
+ void drawTransformedTransparentImage();
+ void drawTransformedSemiTransparentImage_data();
+ void drawTransformedSemiTransparentImage();
+ void drawTransformedFilledImage_data();
+ void drawTransformedFilledImage();
+};
+
+const qreal inv_dist_to_plane = 1. / 1024.;
+QTransform transformForAngle(qreal angle)
+{
+ QTransform transform;
+
+ QTransform rotTrans;
+ rotTrans.translate(-40, 0);
+ QTransform rotTrans2;
+ rotTrans2.translate(40, 0);
+
+ qreal rad = angle * 2. * M_PI / 360.;
+ qreal c = ::cos(rad);
+ qreal s = ::sin(rad);
+
+ qreal x = 0;
+ qreal y = 80;
+ qreal z = 0;
+
+ qreal len = x * x + y * y + z * z;
+ if (len != 1.) {
+ len = ::sqrt(len);
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+
+ QTransform rot(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane,
+ y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane,
+ 0, 0, 1);
+
+ transform *= rotTrans;
+ transform *= rot;
+ transform *= rotTrans2;
+
+ return transform;
+}
+
+void tst_QmlPainting::drawRoundedRect()
+{
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10);
+ }
+ surface.save("regular.png");
+}
+
+void tst_QmlPainting::drawScaledRoundedRect()
+{
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+ p.scale(3, 3);
+
+ QBENCHMARK {
+ p.drawRoundedRect(10, 10, 80, 80, 10, 10);
+ }
+ surface.save("scaled.png");
+}
+
+void tst_QmlPainting::drawTransformedRoundedRect()
+{
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawRoundedRect(100, 100, 80, 80, 10, 10);
+ }
+ surface.save("transformed.png");
+}
+
+void tst_QmlPainting::drawAntialiasedRoundedRect()
+{
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10);
+ }
+ surface.save("aar.png");
+}
+
+void tst_QmlPainting::drawScaledAntialiasedRoundedRect_data()
+{
+ QTest::addColumn<float>("scale");
+
+ for (float i = 0; i < 3; i += .1)
+ QTest::newRow(QString(QLatin1String("scale=%1")).arg(i).toLatin1()) << i;
+}
+
+void tst_QmlPainting::drawScaledAntialiasedRoundedRect()
+{
+ QFETCH(float, scale);
+
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+ p.scale(scale, scale);
+
+ QBENCHMARK {
+ p.drawRoundedRect(10, 10, 80, 80, 10, 10);
+ }
+ surface.save("aas.png");
+}
+
+void tst_QmlPainting::drawTransformedAntialiasedRoundedRect_data()
+{
+ QTest::addColumn<QTransform>("transform");
+
+ for (float angle = 0; angle < 360; angle += 10)
+ QTest::newRow(QString(QLatin1String("angle=%1")).arg(angle).toLatin1()) << transformForAngle(angle);
+}
+
+void tst_QmlPainting::drawTransformedAntialiasedRoundedRect()
+{
+ QFETCH(QTransform, transform);
+
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.setWorldTransform(transform);
+ p.drawRoundedRect(100, 100, 80, 80, 10, 10);
+ }
+ surface.save("aat.png");
+}
+
+void tst_QmlPainting::drawImageRoundedRect()
+{
+ //setup image
+ const int radius = 10;
+ QImage rectImage(81, 81, QImage::Format_ARGB32_Premultiplied);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius);
+
+ //setup surface
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.drawImage(0,0, rectImage);
+ }
+ surface.save("ri.png");
+}
+
+void tst_QmlPainting::drawScaledImageRoundedRect_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QmlPainting::drawScaledImageRoundedRect()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ const int radius = 10;
+ QImage rectImage(81, 81, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+ p.scale(3, 3);
+
+ QBENCHMARK {
+ p.drawImage(0,0, rectImage);
+ }
+ surface.save("si.png");
+}
+
+void tst_QmlPainting::drawTransformedImageRoundedRect_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QmlPainting::drawTransformedImageRoundedRect()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ const int radius = 10;
+ QImage rectImage(81, 81, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(100,100, rectImage);
+ }
+ surface.save("ti.png");
+}
+
+//code from QFxRect for drawing rounded rects
+void tst_QmlPainting::drawScaleGridRoundedRect()
+{
+ //setup image
+ const int pw = 1;
+ const int radius = 10;
+ QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, QImage::Format_ARGB32_Premultiplied);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ if (pw%2)
+ rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius);
+ else
+ rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius);
+
+ //setup surface
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ const int pw = 2;
+ int offset = int(radius+1.5+pw);
+ int width = 80;
+ int height = 80;
+
+ int w = width+pw;
+ int h = height+pw;
+ int xOffset = offset;
+ int xSide = xOffset * 2;
+ bool xMiddles=true;
+ if (xSide > w) {
+ xMiddles=false;
+ xOffset = w/2 + 1;
+ xSide = xOffset * 2;
+ }
+ int yOffset = offset;
+ int ySide = yOffset * 2;
+ bool yMiddles=true;
+ if (ySide > h) {
+ yMiddles = false;
+ yOffset = h/2 + 1;
+ ySide = yOffset * 2;
+ }
+
+ // Upper left
+ p.drawImage(QRect(-pw/2, -pw/2, xOffset, yOffset), rectImage, QRect(0, 0, xOffset, yOffset));
+
+ // Upper middle
+ if (xMiddles)
+ p.drawImage(QRect(xOffset-pw/2, -pw/2, width - xSide + pw, yOffset), rectImage,
+ QRect(rectImage.width()/2, 0, 1, yOffset));
+ // Upper right
+ p.drawImage(QPoint(width-xOffset+pw/2, -pw/2), rectImage,
+ QRect(rectImage.width()-xOffset, 0, xOffset, yOffset));
+ // Middle left
+ if (yMiddles)
+ p.drawImage(QRect(-pw/2, yOffset-pw/2, xOffset, height - ySide + pw), rectImage,
+ QRect(0, rectImage.height()/2, xOffset, 1));
+
+ // Middle
+ if (xMiddles && yMiddles)
+ p.drawImage(QRect(xOffset-pw/2, yOffset-pw/2, width - xSide + pw, height - ySide + pw), rectImage,
+ QRect(rectImage.width()/2, rectImage.height()/2, 1, 1));
+ // Middle right
+ if (yMiddles)
+ p.drawImage(QRect(width-xOffset+pw/2, yOffset-pw/2, xOffset, height - ySide + pw), rectImage,
+ QRect(rectImage.width()-xOffset, rectImage.height()/2, xOffset, 1));
+ // Lower left
+ p.drawImage(QPoint(-pw/2, height - yOffset + pw/2), rectImage, QRect(0, rectImage.height() - yOffset, xOffset, yOffset));
+
+ // Lower Middle
+ if (xMiddles)
+ p.drawImage(QRect(xOffset-pw/2, height - yOffset +pw/2, width - xSide + pw, yOffset), rectImage,
+ QRect(rectImage.width()/2, rectImage.height() - yOffset, 1, yOffset));
+ // Lower Right
+ p.drawImage(QPoint(width-xOffset+pw/2, height - yOffset+pw/2), rectImage,
+ QRect(rectImage.width()-xOffset, rectImage.height() - yOffset, xOffset, yOffset));
+ }
+ surface.save("rsg.png");
+}
+
+void tst_QmlPainting::drawScaledScaleGridRoundedRect_data()
+{
+ QTest::addColumn<float>("scale");
+ QTest::addColumn<int>("imageType");
+
+ for (float i = 0; i < 3; i += .1)
+ QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB32_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB32_Premultiplied;
+ //for (float i = 0; i < 3; i += .1)
+ // QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB8565_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+//code from QFxRect for drawing rounded rects
+void tst_QmlPainting::drawScaledScaleGridRoundedRect()
+{
+ QFETCH(float, scale);
+ QFETCH(int, imageType);
+
+ //setup image
+ const int pw = 1;
+ const int radius = 10;
+ QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ if (pw%2)
+ rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius);
+ else
+ rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+ p.scale(scale, scale);
+
+ QBENCHMARK {
+ const int pw = 2;
+ int offset = int(radius+1.5+pw);
+ int width = 80;
+ int height = 80;
+
+ int w = width+pw;
+ int h = height+pw;
+ int xOffset = offset;
+ int xSide = xOffset * 2;
+ bool xMiddles=true;
+ if (xSide > w) {
+ xMiddles=false;
+ xOffset = w/2 + 1;
+ xSide = xOffset * 2;
+ }
+ int yOffset = offset;
+ int ySide = yOffset * 2;
+ bool yMiddles=true;
+ if (ySide > h) {
+ yMiddles = false;
+ yOffset = h/2 + 1;
+ ySide = yOffset * 2;
+ }
+
+ // Upper left
+ p.drawImage(QRect(10-pw/2, 10-pw/2, xOffset, yOffset), rectImage, QRect(0, 0, xOffset, yOffset));
+
+ // Upper middle
+ if (xMiddles)
+ p.drawImage(QRect(10+xOffset-pw/2, 10+-pw/2, width - xSide + pw, yOffset), rectImage,
+ QRect(rectImage.width()/2, 0, 1, yOffset));
+ // Upper right
+ p.drawImage(QPoint(10+width-xOffset+pw/2, 10+-pw/2), rectImage,
+ QRect(rectImage.width()-xOffset, 0, xOffset, yOffset));
+ // Middle left
+ if (yMiddles)
+ p.drawImage(QRect(10+-pw/2, 10+yOffset-pw/2, xOffset, height - ySide + pw), rectImage,
+ QRect(0, rectImage.height()/2, xOffset, 1));
+
+ // Middle
+ if (xMiddles && yMiddles)
+ p.drawImage(QRect(10+xOffset-pw/2, 10+yOffset-pw/2, width - xSide + pw, height - ySide + pw), rectImage,
+ QRect(rectImage.width()/2, rectImage.height()/2, 1, 1));
+ // Middle right
+ if (yMiddles)
+ p.drawImage(QRect(10+width-xOffset+pw/2, 10+yOffset-pw/2, xOffset, height - ySide + pw), rectImage,
+ QRect(rectImage.width()-xOffset, rectImage.height()/2, xOffset, 1));
+ // Lower left
+ p.drawImage(QPoint(10+-pw/2, 10+height - yOffset + pw/2), rectImage, QRect(0, rectImage.height() - yOffset, xOffset, yOffset));
+
+ // Lower Middle
+ if (xMiddles)
+ p.drawImage(QRect(10+xOffset-pw/2, 10+height - yOffset +pw/2, width - xSide + pw, yOffset), rectImage,
+ QRect(rectImage.width()/2, rectImage.height() - yOffset, 1, yOffset));
+ // Lower Right
+ p.drawImage(QPoint(10+width-xOffset+pw/2, 10+height - yOffset+pw/2), rectImage,
+ QRect(rectImage.width()-xOffset, rectImage.height() - yOffset, xOffset, yOffset));
+ }
+ surface.save("ssg.png");
+}
+
+void tst_QmlPainting::drawTransformedScaleGridRoundedRect_data()
+{
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<int>("imageType");
+
+ for (float angle = 0; angle < 360; angle += 10)
+ QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB32_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB32_Premultiplied;
+ //for (float angle = 0; angle < 360; angle += 10)
+ // QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB8565_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB8565_Premultiplied;
+
+}
+
+//code from QFxRect for drawing rounded rects
+void tst_QmlPainting::drawTransformedScaleGridRoundedRect()
+{
+ QFETCH(QTransform, transform);
+ QFETCH(int, imageType);
+
+ //setup image
+ const int pw = 1;
+ const int radius = 10;
+ QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ if (pw%2)
+ rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius);
+ else
+ rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(transform);
+ const int pw = 2;
+ int offset = int(radius+1.5+pw);
+ int width = 80;
+ int height = 80;
+
+ int w = width+pw;
+ int h = height+pw;
+ int xOffset = offset;
+ int xSide = xOffset * 2;
+ bool xMiddles=true;
+ if (xSide > w) {
+ xMiddles=false;
+ xOffset = w/2 + 1;
+ xSide = xOffset * 2;
+ }
+ int yOffset = offset;
+ int ySide = yOffset * 2;
+ bool yMiddles=true;
+ if (ySide > h) {
+ yMiddles = false;
+ yOffset = h/2 + 1;
+ ySide = yOffset * 2;
+ }
+
+ // Upper left
+ p.drawImage(QRect(100-pw/2, 100-pw/2, xOffset, yOffset), rectImage, QRect(0, 0, xOffset, yOffset));
+
+ // Upper middle
+ if (xMiddles)
+ p.drawImage(QRect(100+xOffset-pw/2, 100+-pw/2, width - xSide + pw, yOffset), rectImage,
+ QRect(rectImage.width()/2, 0, 1, yOffset));
+ // Upper right
+ p.drawImage(QPoint(100+width-xOffset+pw/2, 100+-pw/2), rectImage,
+ QRect(rectImage.width()-xOffset, 0, xOffset, yOffset));
+ // Middle left
+ if (yMiddles)
+ p.drawImage(QRect(100+-pw/2, 100+yOffset-pw/2, xOffset, height - ySide + pw), rectImage,
+ QRect(0, rectImage.height()/2, xOffset, 1));
+
+ // Middle
+ if (xMiddles && yMiddles)
+ p.drawImage(QRect(100+xOffset-pw/2, 100+yOffset-pw/2, width - xSide + pw, height - ySide + pw), rectImage,
+ QRect(rectImage.width()/2, rectImage.height()/2, 1, 1));
+ // Middle right
+ if (yMiddles)
+ p.drawImage(QRect(100+width-xOffset+pw/2, 100+yOffset-pw/2, xOffset, height - ySide + pw), rectImage,
+ QRect(rectImage.width()-xOffset, rectImage.height()/2, xOffset, 1));
+ // Lower left
+ p.drawImage(QPoint(100+-pw/2, 100+height - yOffset + pw/2), rectImage, QRect(0, rectImage.height() - yOffset, xOffset, yOffset));
+
+ // Lower Middle
+ if (xMiddles)
+ p.drawImage(QRect(100+xOffset-pw/2, 100+height - yOffset +pw/2, width - xSide + pw, yOffset), rectImage,
+ QRect(rectImage.width()/2, rectImage.height() - yOffset, 1, yOffset));
+ // Lower Right
+ p.drawImage(QPoint(100+width-xOffset+pw/2, 100+height - yOffset+pw/2), rectImage,
+ QRect(rectImage.width()-xOffset, rectImage.height() - yOffset, xOffset, yOffset));
+ }
+ surface.save("tsg.png");
+}
+
+void tst_QmlPainting::drawTransformedTransparentImage_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QmlPainting::drawTransformedTransparentImage()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ QImage transImage(200, 200, (QImage::Format)imageType);
+ transImage.fill(0);
+
+ //setup surface
+ QImage surface(200, 200, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(0,0, transImage);
+ }
+}
+
+void tst_QmlPainting::drawTransformedSemiTransparentImage_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QmlPainting::drawTransformedSemiTransparentImage()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ QImage transImage(200, 200, (QImage::Format)imageType);
+ transImage.fill(QColor(0,0,0, 128).rgba());
+
+ //setup surface
+ QImage surface(200, 200, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(0,0, transImage);
+ }
+}
+
+void tst_QmlPainting::drawTransformedFilledImage_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QmlPainting::drawTransformedFilledImage()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ QImage filledImage(200, 200, (QImage::Format)imageType);
+ filledImage.fill(QColor(0,0,0).rgb());
+
+ //setup surface
+ QImage surface(200, 200, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(0,0, filledImage);
+ }
+}
+
+QTEST_MAIN(tst_QmlPainting)
+
+#include "tst_qmlpainting.moc"
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index f131c16..9feb90a 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -254,6 +254,7 @@ Configure::Configure( int& argc, char** argv )
dictionary[ "PHONON_BACKEND" ] = "yes";
dictionary[ "DIRECTSHOW" ] = "no";
dictionary[ "WEBKIT" ] = "auto";
+ dictionary[ "DECLARATIVE" ] = "yes";
dictionary[ "PLUGIN_MANIFESTS" ] = "yes";
QString version;
@@ -861,6 +862,10 @@ void Configure::parseCmdLine()
dictionary[ "WEBKIT" ] = "no";
} else if( configCmdLine.at(i) == "-webkit" ) {
dictionary[ "WEBKIT" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-declarative" ) {
+ dictionary[ "DECLARATIVE" ] = "no";
+ } else if( configCmdLine.at(i) == "-declarative" ) {
+ dictionary[ "DECLARATIVE" ] = "yes";
} else if( configCmdLine.at(i) == "-no-plugin-manifests" ) {
dictionary[ "PLUGIN_MANIFESTS" ] = "no";
} else if( configCmdLine.at(i) == "-plugin-manifests" ) {
@@ -1597,6 +1602,8 @@ bool Configure::displayHelp()
desc("WEBKIT", "yes", "-webkit", "Compile in the WebKit module (WebKit is built if a decent C++ compiler is used.)");
desc("SCRIPTTOOLS", "no", "-no-scripttools", "Do not build the QtScriptTools module.");
desc("SCRIPTTOOLS", "yes", "-scripttools", "Build the QtScriptTools module.");
+ desc("DECLARATIVE", "no", "-no-declarative", "Do not build the declarative module");
+ desc("DECLARATIVE", "yes", "-declarative", "Build the declarative module");
desc( "-arch <arch>", "Specify an architecture.\n"
"Available values for <arch>:");
@@ -2278,6 +2285,9 @@ void Configure::generateOutputVars()
if (dictionary["WEBKIT"] == "yes")
qtConfig += "webkit";
+ if (dictionary["DECLARATIVE"] == "yes")
+ qtConfig += "declarative";
+
// We currently have no switch for QtSvg, so add it unconditionally.
qtConfig += "svg";
@@ -2631,6 +2641,7 @@ void Configure::generateConfigfiles()
if(dictionary["DBUS"] == "no") qconfigList += "QT_NO_DBUS";
if(dictionary["IPV6"] == "no") qconfigList += "QT_NO_IPV6";
if(dictionary["WEBKIT"] == "no") qconfigList += "QT_NO_WEBKIT";
+ if(dictionary["DECLARATIVE"] == "no") qconfigList += "QT_NO_DECLARATIVE";
if(dictionary["PHONON"] == "no") qconfigList += "QT_NO_PHONON";
if(dictionary["XMLPATTERNS"] == "no") qconfigList += "QT_NO_XMLPATTERNS";
if(dictionary["SCRIPTTOOLS"] == "no") qconfigList += "QT_NO_SCRIPTTOOLS";
@@ -2891,6 +2902,7 @@ void Configure::displayConfig()
cout << "QtXmlPatterns support......." << dictionary[ "XMLPATTERNS" ] << endl;
cout << "Phonon support.............." << dictionary[ "PHONON" ] << endl;
cout << "WebKit support.............." << dictionary[ "WEBKIT" ] << endl;
+ cout << "Declarative support........." << dictionary[ "DECLARATIVE" ] << endl;
cout << "QtScriptTools support......." << dictionary[ "SCRIPTTOOLS" ] << endl;
cout << "Graphics System............." << dictionary[ "GRAPHICS_SYSTEM" ] << endl;
cout << "Qt3 compatibility..........." << dictionary[ "QT3SUPPORT" ] << endl << endl;
diff --git a/tools/linguist/lupdate/lupdate.h b/tools/linguist/lupdate/lupdate.h
index 2f98643..6db544f 100644
--- a/tools/linguist/lupdate/lupdate.h
+++ b/tools/linguist/lupdate/lupdate.h
@@ -79,6 +79,7 @@ void loadCPP(Translator &translator, const QStringList &filenames, ConversionDat
bool loadJava(Translator &translator, const QString &filename, ConversionData &cd);
bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd);
bool loadUI(Translator &translator, const QString &filename, ConversionData &cd);
+bool loadQml(Translator &translator, const QString &filename, ConversionData &cd);
QT_END_NAMESPACE
diff --git a/tools/linguist/lupdate/lupdate.pro b/tools/linguist/lupdate/lupdate.pro
index ccc2d47..283d69f 100644
--- a/tools/linguist/lupdate/lupdate.pro
+++ b/tools/linguist/lupdate/lupdate.pro
@@ -15,6 +15,9 @@ build_all:!build_pass {
include(../shared/formats.pri)
include(../shared/proparser.pri)
+include($$QT_SOURCE_TREE/src/declarative/qml/parser/parser.pri)
+INCLUDEPATH += $$QT_SOURCE_TREE/src/declarative/qml
+
SOURCES += \
main.cpp \
merge.cpp \
@@ -23,6 +26,7 @@ SOURCES += \
cpp.cpp \
java.cpp \
qscript.cpp \
+ qml.cpp \
ui.cpp
HEADERS += \
diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp
index 8a70b55..f47844f 100644
--- a/tools/linguist/lupdate/main.cpp
+++ b/tools/linguist/lupdate/main.cpp
@@ -428,7 +428,8 @@ int main(int argc, char **argv)
if (!fn.endsWith(QLatin1String(".java"))
&& !fn.endsWith(QLatin1String(".ui"))
&& !fn.endsWith(QLatin1String(".js"))
- && !fn.endsWith(QLatin1String(".qs"))) {
+ && !fn.endsWith(QLatin1String(".qs"))
+ && !fn.endsWith(QLatin1String(".qml"))) {
int offset = 0;
int depth = 0;
do {
@@ -518,6 +519,8 @@ int main(int argc, char **argv)
else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive)
|| it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive))
loadQScript(fetchedTor, *it, cd);
+ else if (it->endsWith(QLatin1String(".qml"), Qt::CaseInsensitive))
+ loadQml(fetchedTor, *it, cd);
else
sourceFilesCpp << *it;
}
diff --git a/tools/linguist/lupdate/qml.cpp b/tools/linguist/lupdate/qml.cpp
new file mode 100644
index 0000000..78a9afd
--- /dev/null
+++ b/tools/linguist/lupdate/qml.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** 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 "lupdate.h"
+
+#include <translator.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+#include "parser/javascriptengine_p.h"
+#include "parser/javascriptparser_p.h"
+#include "parser/javascriptlexer_p.h"
+#include "parser/javascriptnodepool_p.h"
+#include "parser/javascriptastvisitor_p.h"
+#include "parser/javascriptast_p.h"
+
+#include <QCoreApplication>
+#include <QFile>
+#include <QFileInfo>
+#include <QtDebug>
+#include <QStringList>
+
+#include <iostream>
+#include <cstdlib>
+
+using namespace JavaScript;
+
+class FindTrCalls: protected AST::Visitor
+{
+public:
+ void operator()(Translator *translator, const QString &fileName, AST::Node *node)
+ {
+ m_translator = translator;
+ m_fileName = fileName;
+ m_component = QFileInfo(fileName).baseName(); //matches qsTr usage in QScriptEngine
+ accept(node);
+ }
+
+protected:
+ using AST::Visitor::visit;
+ using AST::Visitor::endVisit;
+
+ void accept(AST::Node *node)
+ { AST::Node::acceptChild(node, this); }
+
+ virtual void endVisit(AST::CallExpression *node)
+ {
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(node->base)) {
+ if (idExpr->name->asString() == QLatin1String("qsTr") ||
+ idExpr->name->asString() == QLatin1String("QT_TR_NOOP")) {
+ if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) {
+ AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression);
+ const QString source = literal->value->asString();
+
+ QString comment;
+ bool plural = false;
+ AST::ArgumentList *commentNode = node->arguments->next;
+ if (commentNode) {
+ literal = AST::cast<AST::StringLiteral *>(commentNode->expression);
+ comment = literal->value->asString();
+
+ AST::ArgumentList *nNode = commentNode->next;
+ if (nNode) {
+ AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression);
+ if (numLiteral) {
+ plural = true;
+ }
+ }
+ }
+
+ TranslatorMessage msg(m_component, source,
+ comment, QString(), m_fileName,
+ node->firstSourceLocation().startLine, QStringList(),
+ TranslatorMessage::Unfinished, plural);
+ m_translator->extend(msg);
+ }
+ } else if (idExpr->name->asString() == QLatin1String("qsTranslate") ||
+ idExpr->name->asString() == QLatin1String("QT_TRANSLATE_NOOP")) {
+ if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) {
+ AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression);
+ const QString context = literal->value->asString();
+
+ QString source;
+ QString comment;
+ bool plural = false;
+ AST::ArgumentList *sourceNode = node->arguments->next;
+ if (sourceNode) {
+ literal = AST::cast<AST::StringLiteral *>(sourceNode->expression);
+ source = literal->value->asString();
+ AST::ArgumentList *commentNode = sourceNode->next;
+ if (commentNode) {
+ literal = AST::cast<AST::StringLiteral *>(commentNode->expression);
+ comment = literal->value->asString();
+
+ AST::ArgumentList *nNode = commentNode->next;
+ if (nNode) {
+ AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression);
+ if (numLiteral) {
+ plural = true;
+ }
+ }
+ }
+ }
+
+ TranslatorMessage msg(context, source,
+ comment, QString(), m_fileName,
+ node->firstSourceLocation().startLine, QStringList(),
+ TranslatorMessage::Unfinished, plural);
+ m_translator->extend(msg);
+ }
+
+ }
+ }
+ }
+
+private:
+ Translator *m_translator;
+ QString m_fileName;
+ QString m_component;
+};
+
+QString createErrorString(const QString &filename, const QString &code, Parser &parser)
+{
+ // print out error
+ QStringList lines = code.split(QLatin1Char('\n'));
+ lines.append(QLatin1String("\n")); // sentinel.
+ QString errorString;
+
+ foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
+
+ if (m.isWarning())
+ continue;
+
+ QString error = filename + QLatin1Char(':') + QString::number(m.loc.startLine)
+ + QLatin1Char(':') + QString::number(m.loc.startColumn) + QLatin1String(": error: ")
+ + m.message + QLatin1Char('\n');
+
+ int line = 0;
+ if (m.loc.startLine > 0)
+ line = m.loc.startLine - 1;
+
+ const QString textLine = lines.at(line);
+
+ error += textLine + QLatin1Char('\n');
+
+ int column = m.loc.startColumn - 1;
+ if (column < 0)
+ column = 0;
+
+ column = qMin(column, textLine.length());
+
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = textLine.at(i);
+ if (ch.isSpace())
+ error += ch.unicode();
+ else
+ error += QLatin1Char(' ');
+ }
+ error += QLatin1String("^\n");
+ errorString += error;
+ }
+ return errorString;
+}
+
+bool loadQml(Translator &translator, const QString &filename, ConversionData &cd)
+{
+ cd.m_sourceFileName = filename;
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ cd.appendError(QString::fromLatin1("Cannot open %1: %2")
+ .arg(filename, file.errorString()));
+ return false;
+ }
+
+ const QString code = QTextStream(&file).readAll();
+
+ Engine driver;
+ Parser parser(&driver);
+
+ NodePool nodePool(filename, &driver);
+ driver.setNodePool(&nodePool);
+
+ Lexer lexer(&driver);
+ lexer.setCode(code, /*line = */ 1);
+ driver.setLexer(&lexer);
+
+ if (parser.parse()) {
+ FindTrCalls trCalls;
+ trCalls(&translator, filename, parser.ast());
+ } else {
+ QString error = createErrorString(filename, code, parser);
+ cd.appendError(error);
+ return false;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/codemarker.cpp b/tools/qdoc3/codemarker.cpp
index a803281..1b4b642 100644
--- a/tools/qdoc3/codemarker.cpp
+++ b/tools/qdoc3/codemarker.cpp
@@ -168,7 +168,8 @@ const Node *CodeMarker::nodeForString(const QString& string)
{
if (sizeof(const Node *) == sizeof(uint)) {
return reinterpret_cast<const Node *>(string.toUInt());
- } else {
+ }
+ else {
return reinterpret_cast<const Node *>(string.toULongLong());
}
}
@@ -177,7 +178,8 @@ QString CodeMarker::stringForNode(const Node *node)
{
if (sizeof(const Node *) == sizeof(ulong)) {
return QString::number(reinterpret_cast<ulong>(node));
- } else {
+ }
+ else {
return QString::number(reinterpret_cast<qulonglong>(node));
}
}
@@ -220,7 +222,8 @@ QString CodeMarker::typified(const QString &string)
|| ch.digitValue() >= 0 || ch == QLatin1Char('_')
|| ch == QLatin1Char(':')) {
pendingWord += ch;
- } else {
+ }
+ else {
if (!pendingWord.isEmpty()) {
bool isProbablyType = (pendingWord != QLatin1String("const"));
if (isProbablyType)
@@ -251,7 +254,7 @@ QString CodeMarker::typified(const QString &string)
return result;
}
-QString CodeMarker::taggedNode(const Node *node)
+QString CodeMarker::taggedNode(const Node* node)
{
QString tag;
@@ -276,11 +279,35 @@ QString CodeMarker::taggedNode(const Node *node)
break;
default:
tag = QLatin1String("@unknown");
+ break;
}
return QLatin1Char('<') + tag + QLatin1Char('>') + protect(node->name())
+ QLatin1String("</") + tag + QLatin1Char('>');
}
+#ifdef QDOC_QML
+QString CodeMarker::taggedQmlNode(const Node* node)
+{
+ QString tag;
+ switch (node->type()) {
+ case Node::QmlProperty:
+ tag = QLatin1String("@property");
+ break;
+ case Node::QmlSignal:
+ tag = QLatin1String("@signal");
+ break;
+ case Node::QmlMethod:
+ tag = QLatin1String("@method");
+ break;
+ default:
+ tag = QLatin1String("@unknown");
+ break;
+ }
+ return QLatin1Char('<') + tag + QLatin1Char('>') + protect(node->name())
+ + QLatin1String("</") + tag + QLatin1Char('>');
+}
+#endif
+
QString CodeMarker::linkTag(const Node *node, const QString& body)
{
return QLatin1String("<@link node=\"") + stringForNode(node)
@@ -308,9 +335,11 @@ QString CodeMarker::sortName(const Node *node)
QString sortNo;
if (func->metaness() == FunctionNode::Ctor) {
sortNo = QLatin1String("C");
- } else if (func->metaness() == FunctionNode::Dtor) {
+ }
+ else if (func->metaness() == FunctionNode::Dtor) {
sortNo = QLatin1String("D");
- } else {
+ }
+ else {
if (nodeName.startsWith(QLatin1String("operator"))
&& nodeName.length() > 8
&& !nodeName[8].isLetterOrNumber())
@@ -331,21 +360,32 @@ QString CodeMarker::sortName(const Node *node)
return QLatin1Char('B') + nodeName;
}
-void CodeMarker::insert(FastSection &fastSection, Node *node, SynopsisStyle style, Status status)
+void CodeMarker::insert(FastSection &fastSection,
+ Node *node,
+ SynopsisStyle style,
+ Status status)
{
- bool inheritedMember = (!node->relates() &&
- (node->parent() != (const InnerNode *)fastSection.innerNode));
bool irrelevant = false;
+ bool inheritedMember = false;
+ if (!node->relates()) {
+ if (node->parent() != (const InnerNode*)fastSection.innerNode) {
+ if (node->type() != Node::QmlProperty)
+ inheritedMember = true;
+ }
+ }
if (node->access() == Node::Private) {
irrelevant = true;
- } else if (node->type() == Node::Function) {
+ }
+ else if (node->type() == Node::Function) {
FunctionNode *func = (FunctionNode *) node;
irrelevant = (inheritedMember
&& (func->metaness() == FunctionNode::Ctor ||
func->metaness() == FunctionNode::Dtor));
- } else if (node->type() == Node::Class || node->type() == Node::Enum
- || node->type() == Node::Typedef) {
+ }
+ else if ((node->type() == Node::Class) ||
+ (node->type() == Node::Enum) ||
+ (node->type() == Node::Typedef)) {
irrelevant = (inheritedMember && style != SeparateList);
if (!irrelevant && style == Detailed && node->type() == Node::Typedef) {
const TypedefNode* typedeffe = static_cast<const TypedefNode*>(node);
@@ -357,9 +397,11 @@ void CodeMarker::insert(FastSection &fastSection, Node *node, SynopsisStyle styl
if (!irrelevant) {
if (status == Compat) {
irrelevant = (node->status() != Node::Compat);
- } else if (status == Obsolete) {
+ }
+ else if (status == Obsolete) {
irrelevant = (node->status() != Node::Obsolete);
- } else {
+ }
+ else {
irrelevant = (node->status() == Node::Compat ||
node->status() == Node::Obsolete);
}
@@ -368,9 +410,11 @@ void CodeMarker::insert(FastSection &fastSection, Node *node, SynopsisStyle styl
if (!irrelevant) {
if (!inheritedMember || style == SeparateList) {
QString key = sortName(node);
- if (!fastSection.memberMap.contains(key))
- fastSection.memberMap.insert(key, node);
- } else {
+ if (!fastSection.memberMap.contains(key)) {
+ fastSection.memberMap.insert(key,node);
+ }
+ }
+ else {
if (node->parent()->type() == Node::Class) {
if (fastSection.inherited.isEmpty()
|| fastSection.inherited.last().first != node->parent()) {
@@ -428,7 +472,8 @@ QStringList CodeMarker::macRefsForNode(const Node *node)
#if 0
if (!classe->templateStuff().isEmpty()) {
result += QLatin1String("tmplt/");
- } else
+ }
+ else
#endif
{
result += QLatin1String("cl/");
@@ -465,14 +510,18 @@ QStringList CodeMarker::macRefsForNode(const Node *node)
result += QLatin1String("macro/");
isMacro = true;
#if 0
- } else if (!func->templateStuff().isEmpty()) {
+ }
+ else if (!func->templateStuff().isEmpty()) {
result += QLatin1String("ftmplt/");
#endif
- } else if (func->isStatic()) {
+ }
+ else if (func->isStatic()) {
result += QLatin1String("clm/");
- } else if (!func->parent()->name().isEmpty()) {
+ }
+ else if (!func->parent()->name().isEmpty()) {
result += QLatin1String("instm/");
- } else {
+ }
+ else {
result += QLatin1String("func/");
}
@@ -486,7 +535,8 @@ QStringList CodeMarker::macRefsForNode(const Node *node)
result += "/" + QLatin1String(QMetaObject::normalizedSignature(func->returnType().toLatin1().constData())) + "/(";
const QList<Parameter> &params = func->parameters();
for (int i = 0; i < params.count(); ++i) {
- QString type = params.at(i).leftType() + params.at(i).rightType();
+ QString type = params.at(i).leftType() +
+ params.at(i).rightType();
type = QLatin1String(QMetaObject::normalizedSignature(type.toLatin1().constData()));
if (i != 0)
result += ",";
@@ -529,10 +579,21 @@ QString CodeMarker::macName(const Node *node, const QString &name)
if (node->name().isEmpty()) {
return QLatin1Char('/') + myName;
- } else {
+ }
+ else {
return plainFullName(node) + QLatin1Char('/') + myName;
}
}
+#ifdef QDOC_QML
+/*!
+ Get the list of documentation sections for the children of
+ the specified QmlClassNode.
+ */
+QList<Section> CodeMarker::qmlSections(const QmlClassNode* , SynopsisStyle )
+{
+ return QList<Section>();
+}
+#endif
QT_END_NAMESPACE
diff --git a/tools/qdoc3/codemarker.h b/tools/qdoc3/codemarker.h
index 2bb1f2b..37cb449 100644
--- a/tools/qdoc3/codemarker.h
+++ b/tools/qdoc3/codemarker.h
@@ -114,6 +114,9 @@ class CodeMarker
virtual QString markedUpSynopsis(const Node *node,
const Node *relative,
SynopsisStyle style) = 0;
+#ifdef QDOC_QML
+ virtual QString markedUpQmlItem(const Node* , bool) { return QString(); }
+#endif
virtual QString markedUpName(const Node *node) = 0;
virtual QString markedUpFullName(const Node *node,
const Node *relative = 0) = 0;
@@ -125,6 +128,10 @@ class CodeMarker
virtual QList<Section> sections(const InnerNode *inner,
SynopsisStyle style,
Status status) = 0;
+#ifdef QDOC_QML
+ virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode,
+ SynopsisStyle style);
+#endif
virtual const Node *resolveTarget(const QString& target,
const Tree *tree,
const Node *relative) = 0;
@@ -144,7 +151,10 @@ class CodeMarker
virtual QString sortName(const Node *node);
QString protect(const QString &string);
QString typified(const QString &string);
- QString taggedNode(const Node *node);
+ QString taggedNode(const Node* node);
+#ifdef QDOC_QML
+ QString taggedQmlNode(const Node* node);
+#endif
QString linkTag(const Node *node, const QString& body);
void insert(FastSection &fastSection,
Node *node,
diff --git a/tools/qdoc3/command.cpp b/tools/qdoc3/command.cpp
index a82494d..e121202 100644
--- a/tools/qdoc3/command.cpp
+++ b/tools/qdoc3/command.cpp
@@ -49,44 +49,46 @@
QT_BEGIN_NAMESPACE
-void executeCommand( const Location& location, const QString& format,
- const QStringList& args )
+void executeCommand(const Location& location,
+ const QString& format,
+ const QStringList& args)
{
QString actualCommand;
- for ( int i = 0; i < (int) format.length(); i++ ) {
+ for (int i = 0; i < (int) format.length(); i++) {
int ch = format[i].unicode();
- if ( ch > 0 && ch < 8 ) {
+ if (ch > 0 && ch < 8) {
actualCommand += args[ch - 1];
- } else {
+ }
+ else {
actualCommand += format[i];
}
}
QString toolName = actualCommand;
- int space = toolName.indexOf( QLatin1Char(' ') );
- if ( space != -1 )
- toolName.truncate( space );
+ int space = toolName.indexOf(QLatin1Char(' '));
+ if (space != -1)
+ toolName.truncate(space);
QProcess process;
process.start(QLatin1String("sh"),
- QStringList() << QLatin1String("-c") << actualCommand );
+ QStringList() << QLatin1String("-c") << actualCommand);
process.waitForFinished();
if (process.exitCode() == 127)
- location.fatal( tr("Couldn't launch the '%1' tool")
- .arg(toolName),
- tr("Make sure the tool is installed and in the"
- " path.") );
+ location.fatal(tr("Couldn't launch the '%1' tool")
+ .arg(toolName),
+ tr("Make sure the tool is installed and in the"
+ " path."));
QString errors = QString::fromLocal8Bit(process.readAllStandardError());
- while ( errors.endsWith(QLatin1Char('\n')) )
- errors.truncate( errors.length() - 1 );
- if ( !errors.isEmpty() )
- location.fatal( tr("The '%1' tool encountered some problems")
- .arg(toolName),
- tr("The tool was invoked like this:\n%1\n"
- "It emitted these errors:\n%2")
- .arg(actualCommand).arg(errors) );
+ while (errors.endsWith(QLatin1Char('\n')))
+ errors.truncate(errors.length() - 1);
+ if (!errors.isEmpty())
+ location.fatal(tr("The '%1' tool encountered some problems")
+ .arg(toolName),
+ tr("The tool was invoked like this:\n%1\n"
+ "It emitted these errors:\n%2")
+ .arg(actualCommand).arg(errors));
}
QT_END_NAMESPACE
diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp
index 59b967b..0f35c5d 100644
--- a/tools/qdoc3/cppcodemarker.cpp
+++ b/tools/qdoc3/cppcodemarker.cpp
@@ -43,6 +43,7 @@
cppcodemarker.cpp
*/
+#include <QtCore>
#include "atom.h"
#include "cppcodemarker.h"
#include "node.h"
@@ -283,7 +284,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node,
}
else {
for (int i = 0; i < documentedItems.size(); ++i) {
- if (i < MaxEnumValues - 2 || i == documentedItems.size() - 1) {
+ if (i < MaxEnumValues-2 || i == documentedItems.size()-1) {
if (i != 0)
synopsis += ", ";
synopsis += documentedItems.at(i);
@@ -344,6 +345,43 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node,
return synopsis + extra;
}
+#ifdef QDOC_QML
+/*!
+ */
+QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary)
+{
+ QString name = taggedQmlNode(node);
+ if (summary) {
+ name = linkTag(node,name);
+ }
+ name = "<@name>" + name + "</@name>";
+ QString synopsis = name;
+ if (node->type() == Node::QmlProperty) {
+ const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node);
+ synopsis += " : " + typified(pn->dataType());
+ }
+
+ QString extra;
+ if (summary) {
+ if (node->status() == Node::Preliminary) {
+ extra += " (preliminary)";
+ }
+ else if (node->status() == Node::Deprecated) {
+ extra += " (deprecated)";
+ }
+ else if (node->status() == Node::Obsolete) {
+ extra += " (obsolete)";
+ }
+ }
+
+ if (!extra.isEmpty()) {
+ extra.prepend("<@extra>");
+ extra.append("</@extra>");
+ }
+ return synopsis + extra;
+}
+#endif
+
QString CppCodeMarker::markedUpName(const Node *node)
{
QString name = linkTag(node, taggedNode(node));
@@ -421,29 +459,73 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
const ClassNode *classe = static_cast<const ClassNode *>(inner);
if (style == Summary) {
- FastSection privateFunctions(classe, "Private Functions", "private function",
+ FastSection privateFunctions(classe,
+ "Private Functions",
+ "private function",
"private functions");
- FastSection privateSlots(classe, "Private Slots", "private slot", "private slots");
- FastSection privateTypes(classe, "Private Types", "private type", "private types");
- FastSection protectedFunctions(classe, "Protected Functions", "protected function",
+ FastSection privateSlots(classe,
+ "Private Slots",
+ "private slot",
+ "private slots");
+ FastSection privateTypes(classe,
+ "Private Types",
+ "private type",
+ "private types");
+ FastSection protectedFunctions(classe,
+ "Protected Functions",
+ "protected function",
"protected functions");
- FastSection protectedSlots(classe, "Protected Slots", "protected slot", "protected slots");
- FastSection protectedTypes(classe, "Protected Types", "protected type", "protected types");
- FastSection protectedVariables(classe, "Protected Variables", "protected type", "protected variables");
- FastSection publicFunctions(classe, "Public Functions", "public function",
+ FastSection protectedSlots(classe,
+ "Protected Slots",
+ "protected slot",
+ "protected slots");
+ FastSection protectedTypes(classe,
+ "Protected Types",
+ "protected type",
+ "protected types");
+ FastSection protectedVariables(classe,
+ "Protected Variables",
+ "protected type",
+ "protected variables");
+ FastSection publicFunctions(classe,
+ "Public Functions",
+ "public function",
"public functions");
- FastSection publicSignals(classe, "Signals", "signal", "signals");
- FastSection publicSlots(classe, "Public Slots", "public slot", "public slots");
- FastSection publicTypes(classe, "Public Types", "public type", "public types");
- FastSection publicVariables(classe, "Public Variables", "public type", "public variables");
- FastSection properties(classe, "Properties", "property", "properties");
- FastSection relatedNonMembers(classe, "Related Non-Members", "related non-member",
+ FastSection publicSignals(classe,
+ "Signals",
+ "signal",
+ "signals");
+ FastSection publicSlots(classe,
+ "Public Slots",
+ "public slot",
+ "public slots");
+ FastSection publicTypes(classe,
+ "Public Types",
+ "public type",
+ "public types");
+ FastSection publicVariables(classe,
+ "Public Variables",
+ "public type",
+ "public variables");
+ FastSection properties(classe,
+ "Properties",
+ "property",
+ "properties");
+ FastSection relatedNonMembers(classe,
+ "Related Non-Members",
+ "related non-member",
"related non-members");
- FastSection staticPrivateMembers(classe, "Static Private Members", "static private member",
+ FastSection staticPrivateMembers(classe,
+ "Static Private Members",
+ "static private member",
"static private members");
- FastSection staticProtectedMembers(classe, "Static Protected Members",
- "static protected member", "static protected members");
- FastSection staticPublicMembers(classe, "Static Public Members", "static public member",
+ FastSection staticProtectedMembers(classe,
+ "Static Protected Members",
+ "static protected member",
+ "static protected members");
+ FastSection staticPublicMembers(classe,
+ "Static Public Members",
+ "static public member",
"static public members");
FastSection macros(inner, "Macros", "macro", "macros");
@@ -495,7 +577,7 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
else if (isStatic) {
if ((*c)->type() != Node::Variable
|| !(*c)->doc().isEmpty())
- insert(staticPublicMembers, *c, style, status);
+ insert(staticPublicMembers,*c,style,status);
}
else if ((*c)->type() == Node::Property) {
insert(properties, *c, style, status);
@@ -518,11 +600,11 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
else if (isStatic) {
if ((*c)->type() != Node::Variable
|| !(*c)->doc().isEmpty())
- insert(staticProtectedMembers, *c, style, status);
+ insert(staticProtectedMembers,*c,style,status);
}
else if ((*c)->type() == Node::Variable) {
if (!(*c)->doc().isEmpty())
- insert(protectedVariables, *c, style, status);
+ insert(protectedVariables,*c,style,status);
}
else if ((*c)->type() == Node::Function) {
insert(protectedFunctions, *c, style, status);
@@ -538,13 +620,13 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
else if (isStatic) {
if ((*c)->type() != Node::Variable
|| !(*c)->doc().isEmpty())
- insert(staticPrivateMembers, *c, style, status);
+ insert(staticPrivateMembers,*c,style,status);
}
else if ((*c)->type() == Node::Function) {
- insert(privateFunctions, *c, style, status);
+ insert(privateFunctions,*c,style,status);
}
else {
- insert(privateTypes, *c, style, status);
+ insert(privateTypes,*c,style,status);
}
}
++c;
@@ -661,17 +743,23 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
"Namespaces",
"namespace",
"namespaces");
- FastSection classes(inner, "Classes", "class", "classes");
+ FastSection classes(inner,
+ "Classes",
+ "class",
+ "classes");
FastSection types(inner,
- style == Summary ? "Types" : "Type Documentation",
+ style == Summary ?
+ "Types" : "Type Documentation",
"type",
"types");
FastSection functions(inner,
- style == Summary ? "Functions" : "Function Documentation",
+ style == Summary ?
+ "Functions" : "Function Documentation",
"function",
"functions");
FastSection macros(inner,
- style == Summary ? "Macros" : "Macro Documentation",
+ style == Summary ?
+ "Macros" : "Macro Documentation",
"macro",
"macros");
@@ -1006,4 +1094,82 @@ QString CppCodeMarker::addMarkUp(const QString& protectedCode,
return result;
}
+#ifdef QDOC_QML
+/*!
+ This function is for documenting QML properties. It returns
+ the list of documentation sections for the children of the
+ \a qmlClassNode.
+
+ Currently, it only handles QML property groups.
+ */
+QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode,
+ SynopsisStyle style)
+{
+ QList<Section> sections;
+ if (qmlClassNode) {
+ if (style == Summary) {
+ FastSection qmlproperties(qmlClassNode,
+ "QML Properties",
+ "property",
+ "properties");
+ FastSection qmlsignals(qmlClassNode,
+ "QML Signals",
+ "signal",
+ "signals");
+ FastSection qmlmethods(qmlClassNode,
+ "QML Methods",
+ "method",
+ "methods");
+
+ NodeList::ConstIterator c = qmlClassNode->childNodes().begin();
+ while (c != qmlClassNode->childNodes().end()) {
+ if ((*c)->subType() == Node::QmlPropertyGroup) {
+ const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(*c);
+ NodeList::ConstIterator p = qpgn->childNodes().begin();
+ while (p != qpgn->childNodes().end()) {
+ if ((*p)->type() == Node::QmlProperty) {
+ insert(qmlproperties,*p,style,Okay);
+ }
+ ++p;
+ }
+ }
+ else if ((*c)->type() == Node::QmlSignal) {
+ insert(qmlsignals,*c,style,Okay);
+ }
+ else if ((*c)->type() == Node::QmlMethod) {
+ insert(qmlmethods,*c,style,Okay);
+ }
+ ++c;
+ }
+ append(sections,qmlproperties);
+ append(sections,qmlsignals);
+ append(sections,qmlmethods);
+ }
+ else if (style == Detailed) {
+ FastSection qmlproperties(qmlClassNode,"QML Property Documentation");
+ FastSection qmlsignals(qmlClassNode,"QML Signal Documentation");
+ FastSection qmlmethods(qmlClassNode,"QML Method Documentation");
+ NodeList::ConstIterator c = qmlClassNode->childNodes().begin();
+ while (c != qmlClassNode->childNodes().end()) {
+ if ((*c)->subType() == Node::QmlPropertyGroup) {
+ insert(qmlproperties,*c,style,Okay);
+ }
+ else if ((*c)->type() == Node::QmlSignal) {
+ insert(qmlsignals,*c,style,Okay);
+ }
+ else if ((*c)->type() == Node::QmlMethod) {
+ insert(qmlmethods,*c,style,Okay);
+ }
+ ++c;
+ }
+ append(sections,qmlproperties);
+ append(sections,qmlsignals);
+ append(sections,qmlmethods);
+ }
+ }
+
+ return sections;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/tools/qdoc3/cppcodemarker.h b/tools/qdoc3/cppcodemarker.h
index 8b68bc0..b4c2b43 100644
--- a/tools/qdoc3/cppcodemarker.h
+++ b/tools/qdoc3/cppcodemarker.h
@@ -67,6 +67,9 @@ class CppCodeMarker : public CodeMarker
QString markedUpSynopsis(const Node *node,
const Node *relative,
SynopsisStyle style);
+#ifdef QDOC_QML
+ QString markedUpQmlItem(const Node *node, bool summary);
+#endif
QString markedUpName(const Node *node);
QString markedUpFullName(const Node *node, const Node *relative);
QString markedUpEnumValue(const QString &enumValue, const Node *relative);
@@ -76,6 +79,8 @@ class CppCodeMarker : public CodeMarker
QList<Section> sections(const InnerNode *innerNode,
SynopsisStyle style,
Status status);
+ QList<Section> qmlSections(const QmlClassNode* qmlClassNode,
+ SynopsisStyle style);
const Node *resolveTarget(const QString& target,
const Tree *tree,
const Node *relative);
diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp
index 8baef0c..aec6e8f 100644
--- a/tools/qdoc3/cppcodeparser.cpp
+++ b/tools/qdoc3/cppcodeparser.cpp
@@ -87,6 +87,10 @@ QT_BEGIN_NAMESPACE
#ifdef QDOC_QML
#define COMMAND_QMLCLASS Doc::alias("qmlclass")
#define COMMAND_QMLPROPERTY Doc::alias("qmlproperty")
+#define COMMAND_QMLINHERITS Doc::alias("inherits")
+#define COMMAND_QMLSIGNAL Doc::alias("qmlsignal")
+#define COMMAND_QMLMETHOD Doc::alias("qmlmethod")
+#define COMMAND_QMLDEFAULT Doc::alias("default")
#endif
QStringList CppCodeParser::exampleFiles;
@@ -109,7 +113,8 @@ static void extractPageLinkAndDesc(const QString &arg,
if (arg.contains(".html") && spaceAt != -1) {
*link = arg.left(spaceAt).trimmed();
*desc = arg.mid(spaceAt).trimmed();
- } else {
+ }
+ else {
*link = arg;
*desc = arg;
}
@@ -202,11 +207,6 @@ void CppCodeParser::initializeParser(const Config &config)
nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property);
nodeTypeMap.insert(COMMAND_VARIABLE, Node::Variable);
-#ifdef QDOC_QML
- // nodeTypeMap.insert(COMMAND_QMLCLASS, Node::Class);
- nodeTypeMap.insert(COMMAND_QMLPROPERTY, Node::Property);
-#endif
-
exampleFiles = config.getStringList(CONFIG_EXAMPLES);
exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS);
QStringList exampleFilePatterns = config.getStringList(
@@ -477,13 +477,15 @@ QSet<QString> CppCodeParser::topicCommands()
<< COMMAND_PROPERTY
<< COMMAND_SERVICE
<< COMMAND_TYPEDEF
-#ifdef QDOC_QML
+#ifdef QDOC_QML
<< COMMAND_VARIABLE
<< COMMAND_QMLCLASS
- << COMMAND_QMLPROPERTY;
-#else
+ << COMMAND_QMLPROPERTY
+ << COMMAND_QMLSIGNAL
+ << COMMAND_QMLMETHOD;
+#else
<< COMMAND_VARIABLE;
-#endif
+#endif
}
/*!
@@ -587,7 +589,7 @@ Node *CppCodeParser::processTopicCommand(const Doc& doc,
The command was neither "fn" nor "macro" .
*/
// ### split(" ") hack is there to support header file syntax
- QStringList paths = arg.split(" ");
+ QStringList paths = arg.split(" ");
QStringList path = paths[0].split("::");
Node *node = 0;
if (!usedNamespaces.isEmpty()) {
@@ -627,49 +629,169 @@ Node *CppCodeParser::processTopicCommand(const Doc& doc,
}
}
+ if (command == COMMAND_CLASS) {
+ if (paths.size() > 1) {
+ if (!paths[1].endsWith(".h")) {
+ ClassNode*cnode = static_cast<ClassNode*>(node);
+ cnode->setQmlElement(paths[1]);
+ }
+ }
+ }
return node;
}
else if (command == COMMAND_EXAMPLE) {
- FakeNode *fake = new FakeNode(tre->root(), arg, FakeNode::Example);
+ FakeNode *fake = new FakeNode(tre->root(), arg, Node::Example);
createExampleFileNodes(fake);
return fake;
}
else if (command == COMMAND_EXTERNALPAGE) {
- return new FakeNode(tre->root(), arg, FakeNode::ExternalPage);
+ return new FakeNode(tre->root(), arg, Node::ExternalPage);
}
else if (command == COMMAND_FILE) {
- return new FakeNode(tre->root(), arg, FakeNode::File);
+ return new FakeNode(tre->root(), arg, Node::File);
}
else if (command == COMMAND_GROUP) {
- return new FakeNode(tre->root(), arg, FakeNode::Group);
+ return new FakeNode(tre->root(), arg, Node::Group);
}
else if (command == COMMAND_HEADERFILE) {
- return new FakeNode(tre->root(), arg, FakeNode::HeaderFile);
+ return new FakeNode(tre->root(), arg, Node::HeaderFile);
}
else if (command == COMMAND_MODULE) {
- return new FakeNode(tre->root(), arg, FakeNode::Module);
+ return new FakeNode(tre->root(), arg, Node::Module);
}
else if (command == COMMAND_PAGE) {
- return new FakeNode(tre->root(), arg, FakeNode::Page);
+ return new FakeNode(tre->root(), arg, Node::Page);
}
-#ifdef QDOC_QML
+#ifdef QDOC_QML
else if (command == COMMAND_QMLCLASS) {
const ClassNode* classNode = 0;
- QStringList names = arg.split(" ");
- //qDebug() << "QMLCLASS" << names;
+ QStringList names = arg.split(" ");
if (names.size() > 1) {
Node* n = tre->findNode(names[1].split("::"),Node::Class);
- if (n) {
+ if (n)
classNode = static_cast<const ClassNode*>(n);
- //qDebug() << "FOUND IT!" << classNode->name();
+ }
+ return new QmlClassNode(tre->root(), names[0], classNode);
+ }
+ else if ((command == COMMAND_QMLSIGNAL) ||
+ (command == COMMAND_QMLMETHOD)) {
+ QString element;
+ QString name;
+ QmlClassNode* qmlClass = 0;
+ if (splitQmlArg(doc,arg,element,name)) {
+ Node* n = tre->findNode(QStringList(element),Node::Fake);
+ if (n && n->subType() == Node::QmlClass) {
+ qmlClass = static_cast<QmlClassNode*>(n);
+ if (command == COMMAND_QMLSIGNAL)
+ return new QmlSignalNode(qmlClass,name);
+ else
+ return new QmlMethodNode(qmlClass,name);
}
}
- return new QmlNode(tre->root(), names[0], classNode);
}
-#endif
+#endif
return 0;
}
+#ifdef QDOC_QML
+
+/*!
+ A QML property argument has the form...
+
+ <type> <element>::<name>
+
+ This function splits the argument into those three
+ parts, sets \a type, \a element, and \a property,
+ and returns true. If any of the parts isn't found,
+ a debug message is output and false is returned.
+ */
+bool CppCodeParser::splitQmlPropertyArg(const Doc& doc,
+ const QString& arg,
+ QString& type,
+ QString& element,
+ QString& property)
+{
+ QStringList blankSplit = arg.split(" ");
+ if (blankSplit.size() > 1) {
+ type = blankSplit[0];
+ QStringList colonSplit(blankSplit[1].split("::"));
+ if (colonSplit.size() > 1) {
+ element = colonSplit[0];
+ property = colonSplit[1];
+ return true;
+ }
+ else
+ doc.location().warning(tr("Missing QML element name or property name"));
+ }
+ else
+ doc.location().warning(tr("Missing QML property type or property path"));
+ return false;
+}
+
+/*!
+ A QML signal or method argument has the form...
+
+ <element>::<name>
+
+ This function splits the argument into those two
+ parts, sets \a element, and \a name, and returns
+ true. If either of the parts isn't found, a debug
+ message is output and false is returned.
+ */
+bool CppCodeParser::splitQmlArg(const Doc& doc,
+ const QString& arg,
+ QString& element,
+ QString& name)
+{
+ QStringList colonSplit(arg.split("::"));
+ if (colonSplit.size() > 1) {
+ element = colonSplit[0];
+ name = colonSplit[1];
+ return true;
+ }
+ else
+ doc.location().warning(tr("Missing QML element name or signal/method name"));
+ return false;
+}
+
+/*!
+ Process the topic \a command group with arguments \a args.
+
+ Currently, this function is called only for \e{qmlproperty}.
+ */
+Node *CppCodeParser::processTopicCommandGroup(const Doc& doc,
+ const QString& command,
+ const QStringList& args)
+{
+ QmlPropGroupNode* qmlPropGroup = 0;
+ if (command == COMMAND_QMLPROPERTY) {
+ QString type;
+ QString element;
+ QString property;
+ QStringList::ConstIterator arg = args.begin();
+ if (splitQmlPropertyArg(doc,(*arg),type,element,property)) {
+ Node* n = tre->findNode(QStringList(element),Node::Fake);
+ if (n && n->subType() == Node::QmlClass) {
+ QmlClassNode* qmlClass = static_cast<QmlClassNode*>(n);
+ if (qmlClass)
+ qmlPropGroup = new QmlPropGroupNode(qmlClass,property);
+ }
+ }
+ if (qmlPropGroup) {
+ new QmlPropertyNode(qmlPropGroup,property,type);
+ ++arg;
+ while (arg != args.end()) {
+ if (splitQmlPropertyArg(doc,(*arg),type,element,property)) {
+ new QmlPropertyNode(qmlPropGroup,property,type);
+ }
+ ++arg;
+ }
+ }
+ }
+ return qmlPropGroup;
+}
+#endif
+
/*!
Returns the set of strings representing the common metacommands
plus some other metacommands.
@@ -684,7 +806,13 @@ QSet<QString> CppCodeParser::otherMetaCommands()
<< COMMAND_NEXTPAGE
<< COMMAND_PREVIOUSPAGE
<< COMMAND_INDEXPAGE
+#ifdef QDOC_QML
+ << COMMAND_STARTPAGE
+ << COMMAND_QMLINHERITS
+ << COMMAND_QMLDEFAULT;
+#else
<< COMMAND_STARTPAGE;
+#endif
}
/*!
@@ -751,14 +879,19 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
else if (command == COMMAND_RELATES) {
InnerNode *pseudoParent;
if (arg.startsWith("<") || arg.startsWith("\"")) {
- pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(arg), Node::Fake));
+ pseudoParent =
+ static_cast<InnerNode *>(tre->findNode(QStringList(arg),
+ Node::Fake));
}
else {
QStringList newPath = arg.split("::");
- pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath), Node::Class));
+ pseudoParent =
+ static_cast<InnerNode*>(tre->findNode(QStringList(newPath),
+ Node::Class));
if (!pseudoParent)
- pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath),
- Node::Namespace));
+ pseudoParent =
+ static_cast<InnerNode*>(tre->findNode(QStringList(newPath),
+ Node::Namespace));
}
if (!pseudoParent) {
doc.location().warning(tr("Cannot find '%1' in '\\%2'")
@@ -783,6 +916,15 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
else if (command == COMMAND_STARTPAGE) {
setLink(node, Node::StartLink, arg);
}
+#ifdef QDOC_QML
+ else if (command == COMMAND_QMLINHERITS) {
+ setLink(node, Node::InheritsLink, arg);
+ }
+ else if (command == COMMAND_QMLDEFAULT) {
+ QmlPropGroupNode* qpgn = static_cast<QmlPropGroupNode*>(node);
+ qpgn->setDefault();
+ }
+#endif
else {
processCommonMetaCommand(doc.location(),command,arg,node,tre);
}
@@ -862,9 +1004,8 @@ bool CppCodeParser::match(int target)
readToken();
return true;
}
- else {
+ else
return false;
- }
}
/*!
@@ -899,11 +1040,14 @@ bool CppCodeParser::matchTemplateAngles(CodeChunk *dataType)
do {
if (tok == Tok_LeftAngle) {
leftAngleDepth++;
- } else if (tok == Tok_RightAngle) {
+ }
+ else if (tok == Tok_RightAngle) {
leftAngleDepth--;
- } else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) {
+ }
+ else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) {
++parenAndBraceDepth;
- } else if (tok == Tok_RightParen || tok == Tok_RightBrace) {
+ }
+ else if (tok == Tok_RightParen || tok == Tok_RightBrace) {
if (--parenAndBraceDepth < 0)
return false;
}
@@ -966,7 +1110,8 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
dataType->append(previousLexeme());
else
return false;
- } else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) {
+ }
+ else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) {
dataType->append(previousLexeme());
}
@@ -1066,8 +1211,10 @@ bool CppCodeParser::matchParameter(FunctionNode *func)
readToken();
}
}
- func->addParameter(Parameter(dataType.toString(), "", name,
- defaultValue.toString())); // ###
+ func->addParameter(Parameter(dataType.toString(),
+ "",
+ name,
+ defaultValue.toString())); // ###
return true;
}
@@ -1115,7 +1262,8 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent,
compat = true;
if (tok == Tok_operator &&
- (returnType.toString().isEmpty() || returnType.toString().endsWith("::"))) {
+ (returnType.toString().isEmpty() ||
+ returnType.toString().endsWith("::"))) {
// 'QString::operator const char *()'
parentPath = returnType.toString().split(sep);
parentPath.removeAll(QString());
@@ -1151,11 +1299,10 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent,
name = previousLexeme();
matchTemplateAngles();
- if (match(Tok_Gulbrandsen)) {
+ if (match(Tok_Gulbrandsen))
parentPath.append(name);
- } else {
+ else
break;
- }
}
if (tok == Tok_operator) {
@@ -1168,7 +1315,9 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent,
break;
}
}
- if (parent && (tok == Tok_Semicolon || tok == Tok_LeftBracket || tok == Tok_Colon)
+ if (parent && (tok == Tok_Semicolon ||
+ tok == Tok_LeftBracket ||
+ tok == Tok_Colon)
&& access != Node::Private) {
if (tok == Tok_LeftBracket) {
returnType.appendHotspot();
@@ -1182,7 +1331,8 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent,
}
if (tok != Tok_Semicolon)
return false;
- } else if (tok == Tok_Colon) {
+ }
+ else if (tok == Tok_Colon) {
returnType.appendHotspot();
while (tok != Tok_Semicolon && tok != Tok_Eoi) {
@@ -1374,7 +1524,7 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent)
QString namespaceName = previousLexeme();
NamespaceNode *namespasse = 0;
if (parent)
- namespasse = static_cast<NamespaceNode *>(parent->findNode(namespaceName, Node::Namespace));
+ namespasse = static_cast<NamespaceNode*>(parent->findNode(namespaceName, Node::Namespace));
if (!namespasse) {
namespasse = new NamespaceNode(parent, namespaceName);
namespasse->setAccess(access);
@@ -1440,7 +1590,8 @@ bool CppCodeParser::matchEnumItem(InnerNode *parent, EnumNode *enume)
if (strVal.isEmpty()) {
if (enume->items().isEmpty()) {
strVal = "0";
- } else {
+ }
+ else {
QString last = enume->items().last().value();
bool ok;
int n = last.toInt(&ok);
@@ -1450,15 +1601,16 @@ bool CppCodeParser::matchEnumItem(InnerNode *parent, EnumNode *enume)
strVal = last.left(2) + QString::number(n + 1, 16);
else
strVal = "0" + QString::number(n + 1, 8);
- } else {
- strVal = QString::number(n + 1);
}
+ else
+ strVal = QString::number(n + 1);
}
}
}
enume->addItem(EnumItem(name, strVal));
- } else {
+ }
+ else {
VariableNode *var = new VariableNode(parent, name);
var->setAccess(access);
var->setLocation(location());
@@ -1546,7 +1698,8 @@ bool CppCodeParser::matchProperty(InnerNode *parent)
if (match(Tok_Ident)) {
value = previousLexeme();
- } else if (match(Tok_LeftParen)) {
+ }
+ else if (match(Tok_LeftParen)) {
int depth = 1;
while (tok != Tok_Eoi) {
if (tok == Tok_LeftParen) {
@@ -1799,6 +1952,28 @@ bool CppCodeParser::matchDocsAndStuff()
/*
There is a topic command. Process it.
*/
+#ifdef QDOC_QML
+ if (topic == COMMAND_QMLPROPERTY) {
+ Doc nodeDoc = doc;
+ Node *node = processTopicCommandGroup(nodeDoc,topic,args);
+ if (node != 0) {
+ nodes.append(node);
+ docs.append(nodeDoc);
+ }
+ }
+ else {
+ QStringList::ConstIterator a = args.begin();
+ while (a != args.end()) {
+ Doc nodeDoc = doc;
+ Node *node = processTopicCommand(nodeDoc,topic,*a);
+ if (node != 0) {
+ nodes.append(node);
+ docs.append(nodeDoc);
+ }
+ ++a;
+ }
+ }
+#else
QStringList::ConstIterator a = args.begin();
while (a != args.end()) {
Doc nodeDoc = doc;
@@ -1809,6 +1984,7 @@ bool CppCodeParser::matchDocsAndStuff()
}
++a;
}
+#endif
}
NodeList::Iterator n = nodes.begin();
@@ -1816,7 +1992,8 @@ bool CppCodeParser::matchDocsAndStuff()
while (n != nodes.end()) {
processOtherMetaCommands(*d, *n);
(*n)->setDoc(*d);
- if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) {
+ if ((*n)->isInnerNode() &&
+ ((InnerNode *)*n)->includes().isEmpty()) {
InnerNode *m = static_cast<InnerNode *>(*n);
while (m->parent() != tre->root())
m = m->parent();
@@ -1904,7 +2081,8 @@ void CppCodeParser::parseQiteratorDotH(const Location &location,
mutableSequentialIteratorDefinition = lines[1];
associativeIteratorDefinition = lines[2];
mutableAssociativeIteratorDefinition = lines[3];
- } else {
+ }
+ else {
location.warning(tr("The qiterator.h hack failed"));
}
}
@@ -1986,7 +2164,7 @@ void CppCodeParser::createExampleFileNodes(FakeNode *fake)
foreach (const QString &exampleFile, exampleFiles)
(void) new FakeNode(fake,
exampleFile.mid(sizeOfBoringPartOfName),
- FakeNode::File);
+ Node::File);
}
QT_END_NAMESPACE
diff --git a/tools/qdoc3/cppcodeparser.h b/tools/qdoc3/cppcodeparser.h
index e672654..3864990 100644
--- a/tools/qdoc3/cppcodeparser.h
+++ b/tools/qdoc3/cppcodeparser.h
@@ -90,6 +90,21 @@ class CppCodeParser : public CodeParser
virtual Node *processTopicCommand(const Doc& doc,
const QString& command,
const QString& arg);
+#ifdef QDOC_QML
+ // might need to implement this in QsCodeParser as well.
+ virtual Node *processTopicCommandGroup(const Doc& doc,
+ const QString& command,
+ const QStringList& args);
+ bool splitQmlPropertyArg(const Doc& doc,
+ const QString& arg,
+ QString& type,
+ QString& element,
+ QString& property);
+ bool splitQmlArg(const Doc& doc,
+ const QString& arg,
+ QString& element,
+ QString& name);
+#endif
virtual QSet<QString> otherMetaCommands();
virtual void processOtherMetaCommand(const Doc& doc,
const QString& command,
diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp
index d89d6af..f299420 100644
--- a/tools/qdoc3/generator.cpp
+++ b/tools/qdoc3/generator.cpp
@@ -42,7 +42,7 @@
/*
generator.cpp
*/
-
+#include <QtCore>
#include <qdir.h>
#include "codemarker.h"
@@ -70,12 +70,18 @@ QString Generator::project;
static Text stockLink(const QString &target)
{
- return Text() << Atom(Atom::Link, target) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << target << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ return Text() << Atom(Atom::Link, target)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << target
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
Generator::Generator()
- : amp("&amp;"), lt("&lt;"), gt("&gt;"), quot("&quot;"), tag("</?@[^>]*>")
+ : amp("&amp;"),
+ lt("&lt;"),
+ gt("&gt;"),
+ quot("&quot;"),
+ tag("</?@[^>]*>")
{
generators.prepend(this);
}
@@ -123,7 +129,8 @@ void Generator::initialize(const Config &config)
QSet<QString> formats = config.subVars(imagesDotFileExtensions);
QSet<QString>::ConstIterator f = formats.begin();
while (f != formats.end()) {
- imgFileExts[*f] = config.getStringList(imagesDotFileExtensions + Config::dot + *f);
+ imgFileExts[*f] = config.getStringList(imagesDotFileExtensions +
+ Config::dot + *f);
++f;
}
@@ -131,16 +138,22 @@ void Generator::initialize(const Config &config)
while (g != generators.end()) {
if (outputFormats.contains((*g)->format())) {
(*g)->initializeGenerator(config);
- QStringList extraImages = config.getStringList(CONFIG_EXTRAIMAGES + Config::dot
- + (*g)->format());
+ QStringList extraImages = config.getStringList(CONFIG_EXTRAIMAGES +
+ Config::dot +
+ (*g)->format());
QStringList::ConstIterator e = extraImages.begin();
while (e != extraImages.end()) {
QString userFriendlyFilePath;
- QString filePath = Config::findFile(config.lastLocation(), imageFiles, imageDirs, *e,
- imgFileExts[(*g)->format()], userFriendlyFilePath);
+ QString filePath = Config::findFile(config.lastLocation(),
+ imageFiles, imageDirs, *e,
+ imgFileExts[(*g)->format()],
+ userFriendlyFilePath);
if (!filePath.isEmpty())
- Config::copyFile(config.lastLocation(), filePath, userFriendlyFilePath,
- (*g)->outputDir() + "/images");
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/images");
++e;
}
}
@@ -156,20 +169,23 @@ void Generator::initialize(const Config &config)
QSet<QString> formats = config.subVars(formattingDotName);
QSet<QString>::ConstIterator f = formats.begin();
while (f != formats.end()) {
- QString def = config.getString(formattingDotName + Config::dot +
- *f);
+ QString def = config.getString(formattingDotName +
+ Config::dot + *f);
if (!def.isEmpty()) {
int numParams = Config::numParams(def);
int numOccs = def.count("\1");
if (numParams != 1) {
- config.lastLocation().warning(tr("Formatting '%1' must have exactly one"
- " parameter (found %2)")
- .arg(*n).arg(numParams));
+ config.lastLocation().warning(tr("Formatting '%1' must "
+ "have exactly one "
+ "parameter (found %2)")
+ .arg(*n).arg(numParams));
}
else if (numOccs > 1) {
- config.lastLocation().fatal(tr("Formatting '%1' must contain exactly one"
- " occurrence of '\\1' (found %2)")
+ config.lastLocation().fatal(tr("Formatting '%1' must "
+ "contain exactly one "
+ "occurrence of '\\1' "
+ "(found %2)")
.arg(*n).arg(numOccs));
}
else {
@@ -258,20 +274,33 @@ void Generator::generateText(const Text& text,
}
#ifdef QDOC_QML
+/*!
+ Extract sections of markup text surrounded by \e qmltext
+ and \e endqmltext and output them.
+ */
void Generator::generateQmlText(const Text& text,
const Node *relative,
- CodeMarker *marker)
+ CodeMarker *marker,
+ const QString& qmlName)
{
if (text.firstAtom() != 0) {
startText(relative, marker);
const Atom *atom = text.firstAtom();
while (atom) {
- if (atom->type() != Atom::QmlText)
+ if (atom->type() != Atom::QmlText) {
atom = atom->next();
+ }
else {
+ int n = 0;
atom = atom->next();
while (atom && (atom->type() != Atom::EndQmlText)) {
- int n = 1 + generateAtom(atom, relative, marker);
+ if (atom->string() == relative->name()) {
+ Atom renamed(*atom);
+ renamed.setString(qmlName);
+ n = 1 + generateAtom(&renamed, relative, marker);
+ }
+ else
+ n = 1 + generateAtom(atom, relative, marker);
while (n-- > 0)
atom = atom->next();
}
@@ -295,9 +324,9 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
else if (node->type() == Node::Fake) {
const FakeNode *fake = static_cast<const FakeNode *>(node);
- if (fake->subType() == FakeNode::Example)
+ if (fake->subType() == Node::Example)
generateExampleFiles(fake, marker);
- else if (fake->subType() == FakeNode::File)
+ else if (fake->subType() == Node::File)
quiet = true;
}
@@ -382,7 +411,8 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
FunctionNode *primaryFunc =
func->parent()->findFunctionNode(func->name());
if (primaryFunc) {
- foreach (const Parameter &param, primaryFunc->parameters()) {
+ foreach (const Parameter &param,
+ primaryFunc->parameters()) {
if (param.name() == *a) {
needWarning = false;
break;
@@ -392,7 +422,8 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
if (needWarning)
node->doc().location().warning(
- tr("Undocumented parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node)));
+ tr("Undocumented parameter '%1' in %2")
+ .arg(*a).arg(marker->plainFullName(node)));
}
++a;
}
@@ -412,7 +443,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
if (node->type() == Node::Fake) {
const FakeNode *fake = static_cast<const FakeNode *>(node);
- if (fake->subType() == FakeNode::File) {
+ if (fake->subType() == Node::File) {
Text text;
Quoter quoter;
Doc::quoteFromFile(fake->doc().location(), quoter, fake->name());
@@ -459,7 +490,8 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
if ((*r).access == Node::Protected) {
text << " (protected)";
- } else if ((*r).access == Node::Private) {
+ }
+ else if ((*r).access == Node::Private) {
text << " (private)";
}
text << separator(index++, classe->baseClasses().count());
@@ -470,6 +502,15 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
}
}
+#ifdef QDOC_QML
+/*!
+ */
+void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* )
+{
+ // stub.
+}
+#endif
+
void Generator::generateInheritedBy(const ClassNode *classe,
CodeMarker *marker)
{
@@ -497,18 +538,21 @@ void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker)
QString exampleFile = child->name();
openedList.next();
text << Atom(Atom::ListItemNumber, openedList.numberString())
- << Atom(Atom::ListItemLeft, openedList.styleString()) << Atom::ParaLeft
+ << Atom(Atom::ListItemLeft, openedList.styleString())
+ << Atom::ParaLeft
<< Atom(Atom::Link, exampleFile)
<< Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
<< exampleFile
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << Atom::ParaRight << Atom(Atom::ListItemRight, openedList.styleString());
+ << Atom::ParaRight
+ << Atom(Atom::ListItemRight, openedList.styleString());
}
text << Atom(Atom::ListRight, openedList.styleString());
generateText(text, fake, marker);
}
-void Generator::generateModuleWarning(const ClassNode *classe, CodeMarker *marker)
+void Generator::generateModuleWarning(const ClassNode *classe,
+ CodeMarker *marker)
{
QString module = classe->moduleName();
if (!module.isEmpty()) {
@@ -529,8 +573,10 @@ void Generator::generateModuleWarning(const ClassNode *classe, CodeMarker *marke
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
<< Atom::ParaRight;
}
- else if (module == "Qt3Support" && Tokenizer::isTrue("defined(opensourceedition)")) {
- text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ else if (module == "Qt3Support" &&
+ Tokenizer::isTrue("defined(opensourceedition)")) {
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
<< "Note to Qt Desktop Light Edition users:"
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
<< " This class is only available in the "
@@ -558,10 +604,12 @@ QString Generator::indent(int level, const QString& markedCode)
if (markedCode.at(i - 1) == QLatin1Char('>'))
break;
}
- } else {
+ }
+ else {
if (markedCode.at(i) == QLatin1Char('\n')) {
column = 0;
- } else {
+ }
+ else {
if (column == 0) {
for (int j = 0; j < level; j++)
t += QLatin1Char(' ');
@@ -630,7 +678,7 @@ void Generator::setImageFileExtensions(const QStringList& extensions)
void Generator::unknownAtom(const Atom *atom)
{
Location::internalError(tr("unknown atom type '%1' in %2 generator")
- .arg(atom->typeString()).arg(format()));
+ .arg(atom->typeString()).arg(format()));
}
bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType)
@@ -659,7 +707,8 @@ void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
alternateFunc = func->parent()->findFunctionNode(alternateName);
}
}
- } else if (!func->name().isEmpty()) {
+ }
+ else if (!func->name().isEmpty()) {
alternateName = "set";
alternateName += func->name()[0].toUpper();
alternateName += func->name().mid(1);
@@ -715,9 +764,13 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
case Node::Main:
break;
case Node::Preliminary:
- text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This "
- << typeString(node) << " is under development and is subject to change."
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "This "
+ << typeString(node)
+ << " is under development and is subject to change."
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << Atom::ParaRight;
break;
case Node::Deprecated:
text << Atom::ParaLeft;
@@ -735,16 +788,21 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
text << "This " << typeString(node) << " is obsolete.";
if (node->isInnerNode())
text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD);
- text << " It is provided to keep old source code working. We strongly advise against "
+ text << " It is provided to keep old source code working. "
+ << "We strongly advise against "
<< "using it in new code." << Atom::ParaRight;
break;
case Node::Compat:
// reimplemented in HtmlGenerator subclass
if (node->isInnerNode()) {
- text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This "
- << typeString(node) << " is part of the Qt 3 compatibility layer."
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "This "
+ << typeString(node)
+ << " is part of the Qt 3 compatibility layer."
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
- << " It is provided to keep old source code working. We strongly advise against "
+ << " It is provided to keep old source code working. "
+ << "We strongly advise against "
<< "using it in new code. See "
<< Atom(Atom::AutoLink, "Porting to Qt 4")
<< " for more information."
@@ -768,16 +826,25 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
case Node::UnspecifiedSafeness:
break;
case Node::NonReentrant:
- text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "Warning:"
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " This "
- << typeString(node) << " is not " << stockLink("reentrant") << "." << Atom::ParaRight;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "Warning:"
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << " This "
+ << typeString(node)
+ << " is not "
+ << stockLink("reentrant")
+ << "."
+ << Atom::ParaRight;
break;
case Node::Reentrant:
case Node::ThreadSafe:
- text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
if (parent == Node::ThreadSafe) {
text << "Warning:";
- } else {
+ }
+ else {
text << "Note:";
}
text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " ";
@@ -789,7 +856,9 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
if (node->isInnerNode()) {
const InnerNode *innerNode = static_cast<const InnerNode *>(node);
- text << "All the functions in this " << typeString(node) << " are "
+ text << "All the functions in this "
+ << typeString(node)
+ << " are "
<< theStockLink;
NodeList except;
@@ -815,7 +884,11 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
}
}
else {
- text << "This " << typeString(node) << " is " << theStockLink << ".";
+ text << "This "
+ << typeString(node)
+ << " is "
+ << theStockLink
+ << ".";
}
text << Atom::ParaRight;
}
@@ -826,7 +899,9 @@ void Generator::generateSince(const Node *node, CodeMarker *marker)
{
if (!node->since().isEmpty()) {
Text text;
- text << Atom::ParaLeft << "This " << typeString(node)
+ text << Atom::ParaLeft
+ << "This "
+ << typeString(node)
<< " was introduced in ";
if (project.isEmpty())
text << "version";
@@ -856,7 +931,8 @@ void Generator::generateReimplementedFrom(const FunctionNode *func,
{
if (func->reimplementedFrom() != 0) {
const FunctionNode *from = func->reimplementedFrom();
- if (from->access() != Node::Private && from->parent()->access() != Node::Private) {
+ if (from->access() != Node::Private &&
+ from->parent()->access() != Node::Private) {
Text text;
text << Atom::ParaLeft << "Reimplemented from ";
appendFullName(text, from->parent(), func, marker, from);
@@ -897,8 +973,8 @@ const Atom *Generator::generateAtomList(const Atom *atom,
if (atom->type() == Atom::FormatEndif) {
if (generate && numAtoms0 == numAtoms) {
- relative->location().warning(tr("Output format %1 not handled").
- arg(format()));
+ relative->location().warning(tr("Output format %1 not handled")
+ .arg(format()));
Atom unhandledFormatAtom(Atom::UnhandledFormat, format());
generateAtomList(&unhandledFormatAtom,
relative,
@@ -909,7 +985,8 @@ const Atom *Generator::generateAtomList(const Atom *atom,
atom = atom->next();
}
}
- else if (atom->type() == Atom::FormatElse || atom->type() == Atom::FormatEndif) {
+ else if (atom->type() == Atom::FormatElse ||
+ atom->type() == Atom::FormatEndif) {
return atom;
}
else {
@@ -950,7 +1027,8 @@ void Generator::appendSortedNames(Text& text,
r = classes.begin();
while (r != classes.end()) {
- if ((*r).node->access() == Node::Public && (*r).node->status() != Node::Internal
+ if ((*r).node->access() == Node::Public &&
+ (*r).node->status() != Node::Internal
&& !(*r).node->doc().isEmpty()) {
Text className;
appendFullName(className, (*r).node, classe, marker);
diff --git a/tools/qdoc3/generator.h b/tools/qdoc3/generator.h
index 3db2d8d..9f42160 100644
--- a/tools/qdoc3/generator.h
+++ b/tools/qdoc3/generator.h
@@ -99,7 +99,10 @@ class Generator
#ifdef QDOC_QML
virtual void generateQmlText(const Text& text,
const Node *relative,
- CodeMarker *marker);
+ CodeMarker *marker,
+ const QString& qmlName);
+ virtual void generateQmlInherits(const QmlClassNode* cn,
+ CodeMarker* marker);
#endif
virtual void generateBody(const Node *node, CodeMarker *marker);
virtual void generateAlsoList(const Node *node, CodeMarker *marker);
diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp
index d0fa7c0..16ee5f2 100644
--- a/tools/qdoc3/helpprojectwriter.cpp
+++ b/tools/qdoc3/helpprojectwriter.cpp
@@ -118,16 +118,19 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
typeHash["variable"] = Node::Variable;
typeHash["target"] = Node::Target;
- QHash<QString, FakeNode::SubType> subTypeHash;
- subTypeHash["example"] = FakeNode::Example;
- subTypeHash["headerfile"] = FakeNode::HeaderFile;
- subTypeHash["file"] = FakeNode::File;
- subTypeHash["group"] = FakeNode::Group;
- subTypeHash["module"] = FakeNode::Module;
- subTypeHash["page"] = FakeNode::Page;
- subTypeHash["externalpage"] = FakeNode::ExternalPage;
-
- QSet<FakeNode::SubType> allSubTypes = QSet<FakeNode::SubType>::fromList(subTypeHash.values());
+ QHash<QString, Node::SubType> subTypeHash;
+ subTypeHash["example"] = Node::Example;
+ subTypeHash["headerfile"] = Node::HeaderFile;
+ subTypeHash["file"] = Node::File;
+ subTypeHash["group"] = Node::Group;
+ subTypeHash["module"] = Node::Module;
+ subTypeHash["page"] = Node::Page;
+ subTypeHash["externalpage"] = Node::ExternalPage;
+#ifdef QDOC_QML
+ subTypeHash["qmlclass"] = Node::QmlClass;
+#endif
+
+ QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values());
foreach (const QString &selector, selectors) {
QStringList pieces = selector.split(":");
@@ -139,7 +142,7 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
QString lower = pieces[0].toLower();
pieces = pieces[1].split(",");
if (typeHash.contains(lower)) {
- QSet<FakeNode::SubType> subTypes;
+ QSet<Node::SubType> subTypes;
for (int i = 0; i < pieces.size(); ++i) {
QString lower = pieces[i].toLower();
if (subTypeHash.contains(lower))
@@ -235,7 +238,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
// mask.
const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
if (subproject.selectors[node->type()].contains(fakeNode->subType()) &&
- fakeNode->subType() != FakeNode::ExternalPage &&
+ fakeNode->subType() != Node::ExternalPage &&
!fakeNode->fullTitle().isEmpty())
project.subprojects[name].nodes[objName] = node;
@@ -324,10 +327,10 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
// attributes.
case Node::Fake: {
const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
- if (fakeNode->subType() != FakeNode::ExternalPage &&
+ if (fakeNode->subType() != Node::ExternalPage &&
!fakeNode->fullTitle().isEmpty()) {
- if (fakeNode->subType() != FakeNode::File) {
+ if (fakeNode->subType() != Node::File) {
if (fakeNode->doc().hasKeywords()) {
foreach (const Atom *keyword, fakeNode->doc().keywords()) {
if (!keyword->string().isEmpty()) {
@@ -485,7 +488,7 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer
writer.writeAttribute("title", fakeNode->fullTitle());
// qDebug() << "Title:" << fakeNode->fullTitle();
- if (fakeNode->subType() == FakeNode::HeaderFile) {
+ if (fakeNode->subType() == Node::HeaderFile) {
// Write subsections for all members, obsolete members and Qt 3
// members.
@@ -609,7 +612,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
while (nextPage) {
writeNode(project, writer, nextPage);
nextTitle = nextPage->links().value(Node::NextLink).first;
- if (nextTitle.isEmpty())
+ if(nextTitle.isEmpty())
break;
nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle));
}
diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp
index a2a7184..007f62a 100644
--- a/tools/qdoc3/htmlgenerator.cpp
+++ b/tools/qdoc3/htmlgenerator.cpp
@@ -223,11 +223,21 @@ void HtmlGenerator::initializeGenerator(const Config &config)
i++;
}
- style = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLE);
- postHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTHEADER);
- footer = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_FOOTER);
- address = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_ADDRESS);
- pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_GENERATEMACREFS);
+ style = config.getString(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_STYLE);
+ postHeader = config.getString(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_POSTHEADER);
+ footer = config.getString(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_FOOTER);
+ address = config.getString(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_ADDRESS);
+ pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_GENERATEMACREFS);
project = config.getString(CONFIG_PROJECT);
@@ -241,10 +251,16 @@ void HtmlGenerator::initializeGenerator(const Config &config)
QSet<QString>::ConstIterator edition = editionNames.begin();
while (edition != editionNames.end()) {
QString editionName = *edition;
- QStringList editionModules = config.getStringList(
- CONFIG_EDITION + Config::dot + editionName + Config::dot + "modules");
- QStringList editionGroups = config.getStringList(
- CONFIG_EDITION + Config::dot + editionName + Config::dot + "groups");
+ QStringList editionModules = config.getStringList(CONFIG_EDITION +
+ Config::dot +
+ editionName +
+ Config::dot +
+ "modules");
+ QStringList editionGroups = config.getStringList(CONFIG_EDITION +
+ Config::dot +
+ editionName +
+ Config::dot +
+ "groups");
if (!editionModules.isEmpty())
editionModuleMap[editionName] = editionModules;
@@ -256,11 +272,17 @@ void HtmlGenerator::initializeGenerator(const Config &config)
slow = config.getBool(CONFIG_SLOW);
- stylesheets = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLESHEETS);
- customHeadElements = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_CUSTOMHEADELEMENTS);
+ stylesheets = config.getStringList(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_STYLESHEETS);
+ customHeadElements = config.getStringList(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_CUSTOMHEADELEMENTS);
codeIndent = config.getInt(CONFIG_CODEINDENT);
- helpProjectWriter = new HelpProjectWriter(config, project.toLower() + ".qhp");
+ helpProjectWriter = new HelpProjectWriter(config,
+ project.toLower() +
+ ".qhp");
}
void HtmlGenerator::terminateGenerator()
@@ -303,9 +325,9 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
findAllFunctions(tree->root());
findAllLegaleseTexts(tree->root());
findAllNamespaces(tree->root());
-#ifdef ZZZ_QDOC_QML
+#ifdef ZZZ_QDOC_QML
findAllQmlClasses(tree->root());
-#endif
+#endif
PageGenerator::generateTree(tree, marker);
@@ -409,7 +431,8 @@ int HtmlGenerator::generateAtom(const Atom *atom,
QString str;
atom = atom->next();
while (atom != 0 && atom->type() != Atom::BriefRight) {
- if (atom->type() == Atom::String || atom->type() == Atom::AutoLink)
+ if (atom->type() == Atom::String ||
+ atom->type() == Atom::AutoLink)
str += atom->string();
skipAhead++;
atom = atom->next();
@@ -451,17 +474,23 @@ int HtmlGenerator::generateAtom(const Atom *atom,
marker, relative))
<< "</pre>\n";
break;
-#ifdef QDOC_QML
+#ifdef QDOC_QML
case Atom::Qml:
- out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
- marker, relative))
+ out() << "<pre>"
+ << trimmedTrailing(highlightedCode(indent(codeIndent,
+ atom->string()),
+ marker,
+ relative))
<< "</pre>\n";
break;
-#endif
+#endif
case Atom::CodeNew:
out() << "<p>you can rewrite it as</p>\n"
- << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
- marker, relative))
+ << "<pre>"
+ << trimmedTrailing(highlightedCode(indent(codeIndent,
+ atom->string()),
+ marker,
+ relative))
<< "</pre>\n";
break;
case Atom::CodeOld:
@@ -961,7 +990,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
case Atom::EndQmlText:
// don't do anything with these. They are just tags.
break;
-#endif
+#endif
default:
unknownAtom(atom);
}
@@ -1027,6 +1056,12 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
generateHeader(title, inner, marker, true);
generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
+#ifdef QDOC_QML
+ if (classe && !classe->qmlElement().isEmpty()) {
+ generateInstantiatedBy(classe,marker);
+ }
+#endif
+
generateBrief(inner, marker);
generateIncludes(inner, marker);
generateStatus(inner, marker);
@@ -1045,12 +1080,16 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
out() << "<li><a href=\"" << membersLink << "\">"
<< "List of all members, including inherited members</a></li>\n";
- QString obsoleteLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Obsolete);
+ QString obsoleteLink = generateLowStatusMemberFile(inner,
+ marker,
+ CodeMarker::Obsolete);
if (!obsoleteLink.isEmpty())
out() << "<li><a href=\"" << obsoleteLink << "\">"
<< "Obsolete members</a></li>\n";
- QString compatLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Compat);
+ QString compatLink = generateLowStatusMemberFile(inner,
+ marker,
+ CodeMarker::Compat);
if (!compatLink.isEmpty())
out() << "<li><a href=\"" << compatLink << "\">"
<< "Qt 3 support members</a></li>\n";
@@ -1065,8 +1104,10 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
if (s->members.isEmpty()) {
if (!s->inherited.isEmpty())
needOtherSection = true;
- } else {
- out() << "<a name=\"" << registerRef((*s).name.toLower()) << "\"></a>\n";
+ }
+ else {
+ out() << "<a name=\"" << registerRef((*s).name.toLower())
+ << "\"></a>\n";
out() << "<h3>" << protect((*s).name) << "</h3>\n";
generateSectionList(*s, inner, marker, CodeMarker::Summary);
@@ -1186,16 +1227,19 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
QList<Section>::const_iterator s;
QString htmlTitle = fake->fullTitle();
- if (fake->subType() == FakeNode::File && !fake->subTitle().isEmpty()) {
+ if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) {
subTitleSize = SmallSubTitle;
htmlTitle += " (" + fake->subTitle() + ")";
}
generateHeader(htmlTitle, fake, marker, true);
- generateTitle(fake->fullTitle(), Text() << fake->subTitle(), subTitleSize,
- fake, marker);
+ generateTitle(fake->fullTitle(),
+ Text() << fake->subTitle(),
+ subTitleSize,
+ fake,
+ marker);
- if (fake->subType() == FakeNode::Module) {
+ if (fake->subType() == Node::Module) {
// Generate brief text and status for modules.
generateBrief(fake, marker);
generateStatus(fake, marker);
@@ -1209,7 +1253,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
}
}
- else if (fake->subType() == FakeNode::HeaderFile) {
+ else if (fake->subType() == Node::HeaderFile) {
// Generate brief text and status for modules.
generateBrief(fake, marker);
generateStatus(fake, marker);
@@ -1221,12 +1265,16 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
out() << "<li><a href=\"" << membersLink << "\">"
<< "List of all members, including inherited members</a></li>\n";
- QString obsoleteLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Obsolete);
+ QString obsoleteLink = generateLowStatusMemberFile(fake,
+ marker,
+ CodeMarker::Obsolete);
if (!obsoleteLink.isEmpty())
out() << "<li><a href=\"" << obsoleteLink << "\">"
<< "Obsolete members</a></li>\n";
- QString compatLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Compat);
+ QString compatLink = generateLowStatusMemberFile(fake,
+ marker,
+ CodeMarker::Compat);
if (!compatLink.isEmpty())
out() << "<li><a href=\"" << compatLink << "\">"
<< "Qt 3 support members</a></li>\n";
@@ -1252,7 +1300,49 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
appendDcfSubSection(&fakeSection, compatSection);
}
}
+#ifdef QDOC_QML
+ else if (fake->subType() == Node::QmlClass) {
+ const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake);
+ const ClassNode* cn = qml_cn->classNode();
+ generateQmlInherits(qml_cn, marker);
+ generateQmlInstantiates(qml_cn, marker);
+ generateBrief(qml_cn, marker);
+ sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
+ s = sections.begin();
+ while (s != sections.end()) {
+ out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
+ out() << "<h2>" << protect((*s).name) << "</h2>\n";
+ generateQmlSummary(*s,fake,marker);
+ ++s;
+ }
+ out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
+ out() << "<h2>" << "Detailed Description" << "</h2>\n";
+ generateBody(fake, marker);
+ if (cn)
+ generateQmlText(cn->doc().body(), cn, marker, fake->name());
+ generateAlsoList(fake, marker);
+ out() << "<hr />\n";
+
+ sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
+ s = sections.begin();
+ while (s != sections.end()) {
+ out() << "<h2>" << protect((*s).name) << "</h2>\n";
+ NodeList::ConstIterator m = (*s).members.begin();
+ while (m != (*s).members.end()) {
+ generateDetailedQmlMember(*m, fake, marker);
+ out() << "<br />\n";
+ fakeSection.keywords += qMakePair((*m)->name(),
+ linkForNode(*m,0));
+ ++m;
+ }
+ ++s;
+ }
+ generateFooter(fake);
+ return;
+ }
+#endif
+
sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay);
s = sections.begin();
while (s != sections.end()) {
@@ -1263,24 +1353,12 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
}
Text brief = fake->doc().briefText();
- if (fake->subType() == FakeNode::Module && !brief.isEmpty()) {
+ if (fake->subType() == Node::Module && !brief.isEmpty()) {
out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
out() << "<h2>" << "Detailed Description" << "</h2>\n";
}
generateBody(fake, marker);
-#ifdef QDOC_QML
- if (fake->subType() == FakeNode::QmlClass) {
- //qDebug() << "generateFakeNode(): QML CLASS" << fake->name();
- const QmlNode* qmlNode = static_cast<const QmlNode*>(fake);
- const ClassNode* cn = qmlNode->classNode();
- if (cn) {
- //qDebug() << " CPP CLASS" << cn->name();
- generateQmlText(cn->doc().body(), cn, marker);
- }
- }
-#endif
-
generateAlsoList(fake, marker);
if (!fake->groupMembers().isEmpty()) {
@@ -1310,10 +1388,10 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
}
generateFooter(fake);
- if (fake->subType() == FakeNode::Example) {
+ if (fake->subType() == Node::Example) {
appendDcfSubSection(&dcfExamplesRoot, fakeSection);
}
- else if (fake->subType() != FakeNode::File) {
+ else if (fake->subType() != Node::File) {
QString contentsPage = fake->links().value(Node::ContentsLink).first;
if (contentsPage == "Qt Designer Manual") {
@@ -1561,7 +1639,8 @@ void HtmlGenerator::generateTableOfContents(const Node *node, CodeMarker *marker
QString tdTag;
if (numColumns > 1) {
- tdTag = "<td width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";
+ tdTag = "<td width=\"" +
+ QString::number((100 + numColumns - 1) / numColumns) + "%\">";
out() << "<p><table width=\"100%\">\n<tr valign=\"top\">" << tdTag << "\n";
}
@@ -1581,7 +1660,8 @@ void HtmlGenerator::generateTableOfContents(const Node *node, CodeMarker *marker
out() << "<ul>";
sectionNumber.append("1");
} while (sectionNumber.size() < nextLevel);
- } else {
+ }
+ else {
while (sectionNumber.size() > nextLevel) {
out() << "</ul>\n";
sectionNumber.removeLast();
@@ -1596,7 +1676,10 @@ void HtmlGenerator::generateTableOfContents(const Node *node, CodeMarker *marker
columnSize = 0;
}
out() << "<li>";
- out() << "<a href=\"" << nodeName << "#" << Doc::canonicalTitle(headingText.toString())
+ out() << "<a href=\""
+ << nodeName
+ << "#"
+ << Doc::canonicalTitle(headingText.toString())
<< "\">";
generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
out() << "</a></li>\n";
@@ -1646,12 +1729,15 @@ void HtmlGenerator::generateNavigationBar(const NavigationBar& bar,
}
#endif
-QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker)
+QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner,
+ CodeMarker *marker)
{
QList<Section> sections;
QList<Section>::ConstIterator s;
- sections = marker->sections(inner, CodeMarker::SeparateList, CodeMarker::Okay);
+ sections = marker->sections(inner,
+ CodeMarker::SeparateList,
+ CodeMarker::Okay);
if (sections.isEmpty())
return QString();
@@ -1672,10 +1758,13 @@ QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeM
return fileName;
}
-QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeMarker *marker,
+QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
+ CodeMarker *marker,
CodeMarker::Status status)
{
- QList<Section> sections = marker->sections(inner, CodeMarker::Summary, status);
+ QList<Section> sections = marker->sections(inner,
+ CodeMarker::Summary,
+ status);
QMutableListIterator<Section> j(sections);
while (j.hasNext()) {
if (j.next().members.size() == 0)
@@ -1692,7 +1781,8 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeM
if (status == CodeMarker::Compat) {
title = "Qt 3 Support Members for " + inner->name();
fileName = fileBase(inner) + "-qt3." + fileExtension(inner);
- } else {
+ }
+ else {
title = "Obsolete Members for " + inner->name();
fileName = fileBase(inner) + "-obsolete." + fileExtension(inner);
}
@@ -1706,19 +1796,21 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeM
"<a href=\"qt3support.html\">Qt 3 support layer</a>.</b> "
"They are provided to help you port old code to Qt 4. We advise against "
"using them in new code.</p>\n";
- } else {
- out() << "<p><b>The following class members are obsolete.</b> They are provided to keep "
- "old source code working. We strongly advise against using them in new "
- "code.</p>\n";
+ }
+ else {
+ out() << "<p><b>The following class members are obsolete.</b> "
+ << "They are provided to keep old source code working. "
+ << "We strongly advise against using them in new code.</p>\n";
}
- out() << "<p><ul><li><a href=\"" << linkForNode(inner, 0) << "\">" << protect(inner->name())
+ out() << "<p><ul><li><a href=\""
+ << linkForNode(inner, 0)
+ << "\">" << protect(inner->name())
<< " class reference</a></li></ul></p>\n";
for (i = 0; i < sections.size(); ++i) {
out() << "<h3>" << protect(sections.at(i).name) << "</h3>\n";
-
- generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary);
+ generateSectionList(sections.at(i),inner,marker,CodeMarker::Summary);
}
sections = marker->sections(inner, CodeMarker::Detailed, status);
@@ -1739,8 +1831,10 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeM
return fileName;
}
-void HtmlGenerator::generateClassHierarchy(const Node *relative, CodeMarker *marker,
- const QMap<QString, const Node *> &classMap)
+void HtmlGenerator::generateClassHierarchy(const Node *relative,
+ CodeMarker *marker,
+ const QMap<QString,
+ const Node *> &classMap)
{
if (classMap.isEmpty())
return;
@@ -1762,8 +1856,10 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, CodeMarker *mar
if (stack.top().isEmpty()) {
stack.pop();
out() << "</ul>\n";
- } else {
- const ClassNode *child = static_cast<const ClassNode *>(*stack.top().begin());
+ }
+ else {
+ const ClassNode *child =
+ static_cast<const ClassNode *>(*stack.top().begin());
out() << "<li>";
generateFullName(child, relative, marker);
out() << "</li>\n";
@@ -1782,8 +1878,9 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, CodeMarker *mar
}
}
-void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker,
- const QMap<QString, const Node *> &nodeMap)
+void HtmlGenerator::generateAnnotatedList(const Node *relative,
+ CodeMarker *marker,
+ const QMap<QString, const Node *> &nodeMap)
{
out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
@@ -1806,7 +1903,8 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *mark
generateText(brief, node, marker);
out() << "</td>";
}
- } else {
+ }
+ else {
out() << "<td>";
out() << protect(node->doc().briefText().toString());
out() << "</td>";
@@ -1816,7 +1914,8 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *mark
out() << "</table></p>\n";
}
-void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker,
+void HtmlGenerator::generateCompactList(const Node *relative,
+ CodeMarker *marker,
const QMap<QString, const Node *> &classMap)
{
const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_'
@@ -1860,8 +1959,9 @@ void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker
last = classMap.begin().key();
if (classMap.size() > 1) {
- while (commonPrefixLen < first.length() + 1 && commonPrefixLen < last.length() + 1
- && first[commonPrefixLen] == last[commonPrefixLen])
+ while (commonPrefixLen < first.length() + 1 &&
+ commonPrefixLen < last.length() + 1 &&
+ first[commonPrefixLen] == last[commonPrefixLen])
++commonPrefixLen;
}
@@ -1890,7 +1990,8 @@ void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker
if (key[0].digitValue() != -1) {
paragraphNo = key[0].digitValue();
- } else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
+ }
+ else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
paragraphNo = 10 + key[0].unicode() - 'a';
}
@@ -1945,7 +2046,8 @@ void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker
if (currentOffset[i] >= firstOffset[i + 1]) {
// this column is finished
out() << "<td>\n</td>\n";
- } else {
+ }
+ else {
while (currentOffsetInParagraph[i] == paragraph[currentParagraphNo[i]].count()) {
++currentParagraphNo[i];
currentOffsetInParagraph[i] = 0;
@@ -1987,7 +2089,8 @@ void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker
out() << "</table></p>\n";
}
-void HtmlGenerator::generateFunctionIndex(const Node *relative, CodeMarker *marker)
+void HtmlGenerator::generateFunctionIndex(const Node *relative,
+ CodeMarker *marker)
{
out() << "<p align=\"center\"><font size=\"+1\"><b>";
for (int i = 0; i < 26; i++) {
@@ -2036,7 +2139,8 @@ void HtmlGenerator::generateFunctionIndex(const Node *relative, CodeMarker *mark
#endif
}
-void HtmlGenerator::generateLegaleseList(const Node *relative, CodeMarker *marker)
+void HtmlGenerator::generateLegaleseList(const Node *relative,
+ CodeMarker *marker)
{
QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin();
while (it != legaleseTexts.end()) {
@@ -2054,6 +2158,77 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, CodeMarker *marke
}
}
+/*void HtmlGenerator::generateSynopsis(const Node *node,
+ const Node *relative,
+ CodeMarker *marker,
+ CodeMarker::SynopsisStyle style)
+{
+ QString marked = marker->markedUpSynopsis(node, relative, style);
+ QRegExp templateTag("(<[^@>]*>)");
+ if (marked.indexOf(templateTag) != -1) {
+ QString contents = protect(marked.mid(templateTag.pos(1),
+ templateTag.cap(1).length()));
+ marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
+ contents);
+ }
+ marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
+ "<i>\\1<sub>\\2</sub></i>");
+ marked.replace("<@param>", "<i>");
+ marked.replace("</@param>", "</i>");
+
+ if (style == CodeMarker::Summary)
+ marked.replace("@name>", "b>");
+
+ if (style == CodeMarker::SeparateList) {
+ QRegExp extraRegExp("<@extra>.*</@extra>");
+ extraRegExp.setMinimal(true);
+ marked.replace(extraRegExp, "");
+ }
+ else {
+ marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
+ marked.replace("</@extra>", "</tt>");
+ }
+
+ if (style != CodeMarker::Detailed) {
+ marked.replace("<@type>", "");
+ marked.replace("</@type>", "");
+ }
+ out() << highlightedCode(marked, marker, relative);
+}*/
+
+#ifdef QDOC_QML
+void HtmlGenerator::generateQmlItem(const Node *node,
+ const Node *relative,
+ CodeMarker *marker,
+ bool summary)
+{
+ QString marked = marker->markedUpQmlItem(node,summary);
+ QRegExp templateTag("(<[^@>]*>)");
+ if (marked.indexOf(templateTag) != -1) {
+ QString contents = protect(marked.mid(templateTag.pos(1),
+ templateTag.cap(1).length()));
+ marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
+ contents);
+ }
+ marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
+ "<i>\\1<sub>\\2</sub></i>");
+ marked.replace("<@param>", "<i>");
+ marked.replace("</@param>", "</i>");
+
+ if (summary)
+ marked.replace("@name>", "b>");
+
+ marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
+ marked.replace("</@extra>", "</tt>");
+
+ if (summary) {
+ marked.replace("<@type>", "");
+ marked.replace("</@type>", "");
+ }
+ out() << highlightedCode(marked, marker, relative);
+}
+#endif
+
void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */)
{
QMap<const FakeNode *, QMap<QString, FakeNode *> > fakeNodeMap;
@@ -2076,7 +2251,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
}
// there are too many examples; they would clutter the list
- if (fakeNode->subType() == FakeNode::Example)
+ if (fakeNode->subType() == Node::Example)
continue;
// not interested either in individual (Qt Designer etc.) manual chapters
@@ -2084,7 +2259,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
continue;
// Discard external nodes.
- if (fakeNode->subType() == FakeNode::ExternalPage)
+ if (fakeNode->subType() == Node::ExternalPage)
continue;
QString sortKey = fakeNode->fullTitle().toLower();
@@ -2109,7 +2284,8 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode);
}
}
- } else if (!isGroupPage) {
+ }
+ else if (!isGroupPage) {
// If we encounter a page that belongs to a group then
// we add that page to the list for that group.
const FakeNode *groupNode = static_cast<const FakeNode *>(tre->root()->findNode(group, Node::Fake));
@@ -2596,8 +2772,8 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
i += 2;
if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
- QString link = linkForNode(
- CodeMarker::nodeForString(par1.toString()), relative);
+ const Node* node = CodeMarker::nodeForString(par1.toString());
+ QString link = linkForNode(node, relative);
addLink(link, arg, &html);
}
else {
@@ -2610,7 +2786,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
}
}
-
if (slow) {
// is this block ever used at all?
// replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)"
@@ -2933,10 +3108,9 @@ QString HtmlGenerator::fileBase(const Node *node,
QString HtmlGenerator::fileName(const Node *node)
{
if (node->type() == Node::Fake) {
- if (static_cast<const FakeNode *>(node)->subType() == FakeNode::ExternalPage)
+ if (static_cast<const FakeNode *>(node)->subType() == Node::ExternalPage)
return node->name();
}
-
return PageGenerator::fileName(node);
}
@@ -2958,7 +3132,8 @@ QString HtmlGenerator::refForNode(const Node *node)
typedeffe = static_cast<const TypedefNode *>(node);
if (typedeffe->associatedEnum()) {
return refForNode(typedeffe->associatedEnum());
- } else {
+ }
+ else {
ref = node->name() + "-typedef";
}
break;
@@ -2966,15 +3141,27 @@ QString HtmlGenerator::refForNode(const Node *node)
func = static_cast<const FunctionNode *>(node);
if (func->associatedProperty()) {
return refForNode(func->associatedProperty());
- } else {
+ }
+ else {
ref = func->name();
if (func->overloadNumber() != 1)
ref += "-" + QString::number(func->overloadNumber());
}
break;
case Node::Property:
+#ifdef QDOC_QML
+ case Node::QmlProperty:
+#endif
ref = node->name() + "-prop";
break;
+#ifdef QDOC_QML
+ case Node::QmlSignal:
+ ref = node->name() + "-signal";
+ break;
+ case Node::QmlMethod:
+ ref = node->name() + "-method";
+ break;
+#endif
case Node::Variable:
ref = node->name() + "-var";
break;
@@ -3023,9 +3210,11 @@ QString HtmlGenerator::refForAtom(Atom *atom, const Node * /* node */)
{
if (atom->type() == Atom::SectionLeft) {
return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
- } else if (atom->type() == Atom::Target) {
+ }
+ else if (atom->type() == Atom::Target) {
return Doc::canonicalTitle(atom->string());
- } else {
+ }
+ else {
return QString();
}
}
@@ -3069,7 +3258,10 @@ void HtmlGenerator::generateDetailedMember(const Node *node,
out() << "<a name=\"" + refForNode(node) + "\"></a>";
generateSynopsis(enume, relative, marker, CodeMarker::Detailed);
out() << "<br />";
- generateSynopsis(enume->flagsType(), relative, marker, CodeMarker::Detailed);
+ generateSynopsis(enume->flagsType(),
+ relative,
+ marker,
+ CodeMarker::Detailed);
out() << "</h3>\n";
}
else {
@@ -3218,7 +3410,7 @@ void HtmlGenerator::findAllNamespaces(const InnerNode *node)
}
}
-#ifdef ZZZ_QDOC_QML
+#ifdef ZZZ_QDOC_QML
/*!
This function finds all the qml element nodes and
stores them in a map for later use.
@@ -3229,24 +3421,16 @@ void HtmlGenerator::findAllQmlClasses(const InnerNode *node)
while (c != node->childNodes().constEnd()) {
if ((*c)->type() == Node::Fake) {
const FakeNode* fakeNode = static_cast<const FakeNode *>(*c);
- if (fakeNode->subType() == FakeNode::QmlClass) {
- const QmlNode* qmlNode = static_cast<const QmlNode*>(fakeNode);
- //qDebug() << "HtmlGenerator: QML CLASS" << qmlNode->name();
+ if (fakeNode->subType() == Node::QmlClass) {
+ const QmlClassNode* qmlNode =
+ static_cast<const QmlClassNode*>(fakeNode);
const Node* n = qmlNode->classNode();
- if (n)
- //qDebug() << " FOUND IT!" << n->name();
}
qmlClasses.insert(fakeNode->name(),*c);
}
++c;
}
}
-#endif
-
-#if 0
- else if ((*c)->isInnerNode()) {
- findAllClasses(static_cast<InnerNode *>(*c));
- }
#endif
int HtmlGenerator::hOffset(const Node *node)
@@ -3510,3 +3694,212 @@ void HtmlGenerator::endLink()
}
QT_END_NAMESPACE
+
+#ifdef QDOC_QML
+
+/*!
+ Generates the summary for for the \a section. Only used for
+ sections of QML element documentation.
+
+ Currently handles only the QML property group.
+ */
+void HtmlGenerator::generateQmlSummary(const Section& section,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ if (!section.members.isEmpty()) {
+ NodeList::ConstIterator m;
+ int count = section.members.size();
+ bool twoColumn = false;
+ if (section.members.first()->type() == Node::QmlProperty) {
+ twoColumn = (count >= 5);
+ }
+ if (twoColumn)
+ out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\""
+ " cellspacing=\"0\">\n"
+ << "<tr><td width=\"45%\" valign=\"top\">";
+ out() << "<ul>\n";
+
+ int row = 0;
+ m = section.members.begin();
+ while (m != section.members.end()) {
+ if (twoColumn && row == (int) (count + 1) / 2)
+ out() << "</ul></td><td valign=\"top\"><ul>\n";
+ out() << "<li><div class=\"fn\"></div>";
+ generateQmlItem(*m,relative,marker,true);
+ out() << "</li>\n";
+ row++;
+ ++m;
+ }
+ out() << "</ul>\n";
+ if (twoColumn)
+ out() << "</td></tr>\n</table></p>\n";
+ }
+}
+
+/*!
+ Outputs the html detailed documentation for a section
+ on a QML element reference page.
+ */
+void HtmlGenerator::generateDetailedQmlMember(const Node *node,
+ const InnerNode *relative,
+ CodeMarker *marker)
+{
+ const QmlPropertyNode* qpn = 0;
+ generateMacRef(node, marker);
+ out() << "<div class=\"qmlitem\">";
+ if (node->subType() == Node::QmlPropertyGroup) {
+ const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
+ NodeList::ConstIterator p = qpgn->childNodes().begin();
+ out() << "<div class=\"qmlproto\">";
+ out() << "<table class=\"qmlname\">";
+
+ while (p != qpgn->childNodes().end()) {
+ if ((*p)->type() == Node::QmlProperty) {
+ qpn = static_cast<const QmlPropertyNode*>(*p);
+ out() << "<tr><td>";
+ out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
+ generateQmlItem(qpn, relative, marker, false);
+ out() << "</td></tr>";
+ if (qpgn->isDefault()) {
+ out() << "<div class=\"qmlitem\">"
+ << "<div class=\"qmlproto\">"
+ << "<table class=\"qmlname\">"
+ << "<tr><td><font color=\"green\">"
+ << "default</font></td></tr>";
+ }
+ }
+ ++p;
+ }
+ out() << "</table>";
+ out() << "</div>";
+ }
+ else if (node->type() == Node::QmlSignal) {
+ const QmlSignalNode* qsn = static_cast<const QmlSignalNode*>(node);
+ out() << "<div class=\"qmlproto\">";
+ out() << "<table class=\"qmlname\">";
+ out() << "<tr><td>";
+ out() << "<a name=\"" + refForNode(qsn) + "\"></a>";
+ generateQmlItem(qsn,relative,marker,false);
+ out() << "</td></tr>";
+ out() << "</table>";
+ out() << "</div>";
+ }
+ else if (node->type() == Node::QmlMethod) {
+ const QmlMethodNode* qmn = static_cast<const QmlMethodNode*>(node);
+ out() << "<div class=\"qmlproto\">";
+ out() << "<table class=\"qmlname\">";
+ out() << "<tr><td>";
+ out() << "<a name=\"" + refForNode(qmn) + "\"></a>";
+ generateQmlItem(qmn,relative,marker,false);
+ out() << "</td></tr>";
+ out() << "</table>";
+ out() << "</div>";
+ }
+ out() << "<div class=\"qmldoc\">";
+ generateStatus(node, marker);
+ generateBody(node, marker);
+ generateThreadSafeness(node, marker);
+ generateSince(node, marker);
+ generateAlsoList(node, marker);
+ out() << "</div>";
+ out() << "</div>";
+}
+
+/*!
+ Output the "Inherits" line for the QML element,
+ if there should be one.
+ */
+void HtmlGenerator::generateQmlInherits(const QmlClassNode* cn,
+ CodeMarker* marker)
+{
+ if (cn && !cn->links().empty()) {
+ if (cn->links().contains(Node::InheritsLink)) {
+ QPair<QString,QString> linkPair;
+ linkPair = cn->links()[Node::InheritsLink];
+ QStringList strList(linkPair.first);
+ const Node* n = tre->findNode(strList,Node::Fake);
+ if (n && n->subType() == Node::QmlClass) {
+ const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
+ out() << "<p style=\"text-align: center\">";
+ Text text;
+ text << "[Inherits ";
+ text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ text << Atom(Atom::String, linkPair.second);
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ text << "]";
+ generateText(text, cn, marker);
+ out() << "</p>";
+ }
+ else
+ qDebug() << "generateQmlInherits(): "
+ << "Inherited element not documented -->"
+ << linkPair.first;
+ }
+ }
+}
+
+/*!
+ Output the "[Xxx instantiates the C++ class QFxXxx]"
+ line for the QML element, if there should be one.
+
+ If there is no class node, or if the class node status
+ is set to Node::Internal, do nothing.
+ */
+void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn,
+ CodeMarker* marker)
+{
+ const ClassNode* cn = qcn->classNode();
+ if (cn && (cn->status() != Node::Internal)) {
+ out() << "<p style=\"text-align: center\">";
+ Text text;
+ text << "[";
+ text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ text << Atom(Atom::String, qcn->name());
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ text << " instantiates the C++ class ";
+ text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ text << Atom(Atom::String, cn->name());
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ text << "]";
+ generateText(text, qcn, marker);
+ out() << "</p>";
+ }
+}
+
+/*!
+ Output the "[QFxXxx is instantiated by QML element Xxx]"
+ line for the class, if there should be one.
+
+ If there is no QML element, or if the class node status
+ is set to Node::Internal, do nothing.
+ */
+void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn,
+ CodeMarker* marker)
+{
+ if (cn && cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) {
+ const Node* n = tre->root()->findNode(cn->qmlElement(),Node::Fake);
+ if (n && n->subType() == Node::QmlClass) {
+ out() << "<p style=\"text-align: center\">";
+ Text text;
+ text << "[";
+ text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ text << Atom(Atom::String, cn->name());
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ text << " is instantiated by QML element ";
+ text << Atom(Atom::LinkNode,CodeMarker::stringForNode(n));
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ text << Atom(Atom::String, n->name());
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ text << "]";
+ generateText(text, cn, marker);
+ out() << "</p>";
+ }
+ }
+}
+
+#endif
diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h
index ec9532f..3e3dbf2 100644
--- a/tools/qdoc3/htmlgenerator.h
+++ b/tools/qdoc3/htmlgenerator.h
@@ -145,6 +145,21 @@ class HtmlGenerator : public PageGenerator
const Node *relative,
CodeMarker *marker,
CodeMarker::SynopsisStyle style);
+#ifdef QDOC_QML
+ void generateQmlSummary(const Section& section,
+ const Node *relative,
+ CodeMarker *marker);
+ void generateQmlItem(const Node *node,
+ const Node *relative,
+ CodeMarker *marker,
+ bool summary);
+ void generateDetailedQmlMember(const Node *node,
+ const InnerNode *relative,
+ CodeMarker *marker);
+ void generateQmlInherits(const QmlClassNode* cn, CodeMarker* marker);
+ void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker);
+ void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker);
+#endif
#ifdef QDOC_NAME_ALIGNMENT
void generateSynopsis(const Node *node,
const Node *relative,
@@ -175,8 +190,12 @@ class HtmlGenerator : public PageGenerator
const Node *relative,
CodeMarker *marker,
const Node *actualNode = 0);
- void generateDetailedMember(const Node *node, const InnerNode *relative, CodeMarker *marker);
- void generateLink(const Atom *atom, const Node *relative, CodeMarker *marker);
+ void generateDetailedMember(const Node *node,
+ const InnerNode *relative,
+ CodeMarker *marker);
+ void generateLink(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker);
void generateStatus(const Node *node, CodeMarker *marker);
QString registerRef(const QString& ref);
diff --git a/tools/qdoc3/jambiapiparser.cpp b/tools/qdoc3/jambiapiparser.cpp
index 73d10a6..05c7be8 100644
--- a/tools/qdoc3/jambiapiparser.cpp
+++ b/tools/qdoc3/jambiapiparser.cpp
@@ -234,8 +234,9 @@ void JambiApiParser::doneParsingSourceFiles(Tree * /* tree */)
foreach (Node *cppNode, cppTre->root()->childNodes()) {
if (cppNode->type() == Node::Fake) {
FakeNode *cppFake = static_cast<FakeNode *>(cppNode);
- if (cppFake->subType() == FakeNode::Page) {
- FakeNode *javaFake = new FakeNode(javaTre->root(), cppFake->name(),
+ if (cppFake->subType() == Node::Page) {
+ FakeNode *javaFake = new FakeNode(javaTre->root(),
+ cppFake->name(),
cppFake->subType());
javaFake->setModuleName("com.trolltech.qt"); // ### hard-coded
javaFake->setTitle(cppFake->title());
diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp
index 231149e..4734374 100644
--- a/tools/qdoc3/node.cpp
+++ b/tools/qdoc3/node.cpp
@@ -43,6 +43,7 @@
node.cpp
*/
+#include <QtCore>
#include "node.h"
QT_BEGIN_NAMESPACE
@@ -113,6 +114,9 @@ void Node::setRelates(InnerNode *pseudoParent)
}
/*!
+ This function creates a pair that describes a link.
+ The pair is composed from \a link and \a desc. The
+ \a linkType is the map index the pair is filed under.
*/
void Node::setLink(LinkType linkType, const QString &link, const QString &desc)
{
@@ -623,7 +627,7 @@ void InnerNode::removeRelated(Node *pseudoChild)
*/
/*!
- Returns false because this is an InnerNode.
+ Returns false because this is a LeafNode.
*/
bool LeafNode::isInnerNode() const
{
@@ -713,9 +717,11 @@ void ClassNode::fixBaseClasses()
*/
/*!
+ The type of a FakeNode is Fake, and it has a \a subtype,
+ which specifies the type of FakeNode.
*/
-FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subType)
- : InnerNode(Fake, parent, name), sub(subType)
+FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subtype)
+ : InnerNode(Fake, parent, name), sub(subtype)
{
}
@@ -1021,4 +1027,98 @@ bool TargetNode::isInnerNode() const
return false;
}
+#ifdef QDOC_QML
+/*!
+ Constructor for the Qml class node.
+ */
+QmlClassNode::QmlClassNode(InnerNode *parent,
+ const QString& name,
+ const ClassNode* cn)
+ : FakeNode(parent, name, QmlClass), cnode(cn)
+{
+ setTitle("QML " + name + " Element Reference");
+}
+
+/*!
+ The base file name for this kind of node has "qml_"
+ prepended to it.
+
+ But not yet. Still testing.
+ */
+QString QmlClassNode::fileBase() const
+{
+#if 0
+ if (Node::fileBase() == "item")
+ qDebug() << "FILEBASE: qmlitem" << name();
+ return "qml_" + Node::fileBase();
+#endif
+ return Node::fileBase();
+}
+
+/*!
+ Constructor for the Qml property group node. \a parent is
+ always a QmlClassNode.
+ */
+QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent, const QString& name)
+ : FakeNode(parent, name, QmlPropertyGroup), isdefault(false)
+{
+ // nothing.
+}
+
+/*!
+ Constructor for the QML property node.
+ */
+QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent,
+ const QString& name,
+ const QString& type)
+ : LeafNode(QmlProperty, parent, name),
+ dt(type),
+ sto(Trool_Default),
+ des(Trool_Default)
+{
+ // nothing.
+}
+
+/*!
+ I don't know what this is.
+ */
+QmlPropertyNode::Trool QmlPropertyNode::toTrool(bool boolean)
+{
+ return boolean ? Trool_True : Trool_False;
+}
+
+/*!
+ I don't know what this is either.
+ */
+bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue)
+{
+ switch (troolean) {
+ case Trool_True:
+ return true;
+ case Trool_False:
+ return false;
+ default:
+ return defaultValue;
+ }
+}
+
+/*!
+ Constructor for the QML signal node.
+ */
+QmlSignalNode::QmlSignalNode(QmlClassNode *parent, const QString& name)
+ : LeafNode(QmlSignal, parent, name)
+{
+ // nothing.
+}
+
+/*!
+ Constructor for the QML method node.
+ */
+QmlMethodNode::QmlMethodNode(QmlClassNode *parent, const QString& name)
+ : LeafNode(QmlMethod, parent, name)
+{
+ // nothing.
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h
index c34b82b..9024758 100644
--- a/tools/qdoc3/node.h
+++ b/tools/qdoc3/node.h
@@ -72,7 +72,31 @@ class Node
Function,
Property,
Variable,
+#ifdef QDOC_QML
+ Target,
+ QmlProperty,
+ QmlSignal,
+ QmlMethod
+#else
Target
+#endif
+ };
+
+ enum SubType {
+ NoSubType,
+ Example,
+ HeaderFile,
+ File,
+ Group,
+ Module,
+ Page,
+#ifdef QDOC_QML
+ ExternalPage,
+ QmlClass,
+ QmlPropertyGroup
+#else
+ ExternalPage
+#endif
};
enum Access { Public, Protected, Private };
@@ -99,7 +123,8 @@ class Node
NextLink,
PreviousLink,
ContentsLink,
- IndexLink /*,
+ IndexLink,
+ InheritsLink /*,
GlossaryLink,
CopyrightLink,
ChapterLink,
@@ -124,6 +149,7 @@ class Node
virtual bool isInnerNode() const = 0;
Type type() const { return typ; }
+ virtual SubType subType() const { return NoSubType; }
InnerNode *parent() const { return par; }
InnerNode *relates() const { return rel; }
const QString& name() const { return nam; }
@@ -143,7 +169,7 @@ class Node
void clearRelated() { rel = 0; }
- QString fileBase() const;
+ virtual QString fileBase() const;
protected:
Node(Type type, InnerNode *parent, const QString& name);
@@ -180,7 +206,7 @@ typedef QList<Node *> NodeList;
class InnerNode : public Node
{
public:
- ~InnerNode();
+ virtual ~InnerNode();
Node *findNode(const QString& name);
Node *findNode(const QString& name, Type type);
@@ -202,6 +228,7 @@ class InnerNode : public Node
const EnumNode *findEnumNodeForValue(const QString &enumValue) const;
const NodeList & childNodes() const { return children; }
const NodeList & relatedNodes() const { return related; }
+ int count() const { return children.size(); }
int overloadNumber(const FunctionNode *func) const;
int numOverloads(const QString& funcName) const;
NodeList overloads(const QString &funcName) const;
@@ -231,17 +258,19 @@ class LeafNode : public Node
{
public:
LeafNode();
+ virtual ~LeafNode() { }
virtual bool isInnerNode() const;
protected:
- LeafNode(Type type, InnerNode *parent, const QString& name);
+ LeafNode(Type type, InnerNode* parent, const QString& name);
};
class NamespaceNode : public InnerNode
{
public:
NamespaceNode(InnerNode *parent, const QString& name);
+ virtual ~NamespaceNode() { }
};
class ClassNode;
@@ -265,6 +294,7 @@ class ClassNode : public InnerNode
{
public:
ClassNode(InnerNode *parent, const QString& name);
+ virtual ~ClassNode() { }
void addBaseClass(Access access,
ClassNode *node,
@@ -279,29 +309,23 @@ class ClassNode : public InnerNode
QString serviceName() const { return sname; }
void setServiceName(const QString& value) { sname = value; }
+ QString qmlElement() const { return qmlelement; }
+ void setQmlElement(const QString& value) { qmlelement = value; }
private:
QList<RelatedClass> bas;
QList<RelatedClass> der;
bool hidden;
QString sname;
+ QString qmlelement;
};
class FakeNode : public InnerNode
{
public:
- enum SubType {
- Example,
- HeaderFile,
- File,
- Group,
- Module,
- Page,
- ExternalPage,
- QmlClass
- };
FakeNode(InnerNode *parent, const QString& name, SubType subType);
+ virtual ~FakeNode() { }
void setTitle(const QString &title) { tle = title; }
void setSubTitle(const QString &subTitle) { stle = subTitle; }
@@ -320,18 +344,85 @@ class FakeNode : public InnerNode
NodeList gr;
};
-class QmlNode : public FakeNode
+#ifdef QDOC_QML
+class QmlClassNode : public FakeNode
{
public:
- QmlNode(InnerNode *parent, const QString& name, const ClassNode* cn)
- : FakeNode(parent, name, QmlClass), cnode(cn) { }
+ QmlClassNode(InnerNode *parent,
+ const QString& name,
+ const ClassNode* cn);
+ virtual ~QmlClassNode() { }
const ClassNode* classNode() const { return cnode; }
+ virtual QString fileBase() const;
private:
const ClassNode* cnode;
};
+class QmlPropGroupNode : public FakeNode
+{
+ public:
+ QmlPropGroupNode(QmlClassNode* parent, const QString& name);
+ virtual ~QmlPropGroupNode() { }
+
+ const QString& element() const { return name(); }
+ void setDefault() { isdefault = true; }
+ bool isDefault() const { return isdefault; }
+
+ private:
+ bool isdefault;
+};
+
+class QmlPropertyNode : public LeafNode
+{
+ public:
+ QmlPropertyNode(QmlPropGroupNode* parent,
+ const QString& name,
+ const QString& type);
+ virtual ~QmlPropertyNode() { }
+
+ void setDataType(const QString& dataType) { dt = dataType; }
+ void setStored(bool stored) { sto = toTrool(stored); }
+ void setDesignable(bool designable) { des = toTrool(designable); }
+
+ const QString &dataType() const { return dt; }
+ QString qualifiedDataType() const { return dt; }
+ bool isStored() const { return fromTrool(sto,true); }
+ bool isDesignable() const { return fromTrool(des,false); }
+
+ const QString& element() const { return parent()->name(); }
+
+ private:
+ enum Trool { Trool_True, Trool_False, Trool_Default };
+
+ static Trool toTrool(bool boolean);
+ static bool fromTrool(Trool troolean, bool defaultValue);
+
+ QString dt;
+ Trool sto;
+ Trool des;
+};
+
+class QmlSignalNode : public LeafNode
+{
+ public:
+ QmlSignalNode(QmlClassNode* parent, const QString& name);
+ virtual ~QmlSignalNode() { }
+
+ const QString& element() const { return parent()->name(); }
+};
+
+class QmlMethodNode : public LeafNode
+{
+ public:
+ QmlMethodNode(QmlClassNode* parent, const QString& name);
+ virtual ~QmlMethodNode() { }
+
+ const QString& element() const { return parent()->name(); }
+};
+#endif
+
class EnumItem
{
public:
@@ -357,6 +448,7 @@ class EnumNode : public LeafNode
{
public:
EnumNode(InnerNode *parent, const QString& name);
+ virtual ~EnumNode() { }
void addItem(const EnumItem& item);
void setFlagsType(TypedefNode *typedeff);
@@ -377,6 +469,7 @@ class TypedefNode : public LeafNode
{
public:
TypedefNode(InnerNode *parent, const QString& name);
+ virtual ~TypedefNode() { }
const EnumNode *associatedEnum() const { return ae; }
@@ -437,6 +530,7 @@ class FunctionNode : public LeafNode
enum Virtualness { NonVirtual, ImpureVirtual, PureVirtual };
FunctionNode(InnerNode *parent, const QString &name);
+ virtual ~FunctionNode() { }
void setReturnType(const QString& returnType) { rt = returnType; }
void setMetaness(Metaness metaness) { met = metaness; }
@@ -496,6 +590,7 @@ class PropertyNode : public LeafNode
enum { NumFunctionRoles = Resetter + 1 };
PropertyNode(InnerNode *parent, const QString& name);
+ virtual ~PropertyNode() { }
void setDataType(const QString& dataType) { dt = dataType; }
void addFunction(FunctionNode *function, FunctionRole role);
@@ -553,6 +648,7 @@ class VariableNode : public LeafNode
{
public:
VariableNode(InnerNode *parent, const QString &name);
+ virtual ~VariableNode() { }
void setLeftType(const QString &leftType) { lt = leftType; }
void setRightType(const QString &rightType) { rt = rightType; }
@@ -578,6 +674,7 @@ class TargetNode : public LeafNode
{
public:
TargetNode(InnerNode *parent, const QString& name);
+ virtual ~TargetNode() { }
virtual bool isInnerNode() const;
};
diff --git a/tools/qdoc3/pagegenerator.cpp b/tools/qdoc3/pagegenerator.cpp
index 2d50279..e92a067 100644
--- a/tools/qdoc3/pagegenerator.cpp
+++ b/tools/qdoc3/pagegenerator.cpp
@@ -81,30 +81,50 @@ QString PageGenerator::fileBase(const Node *node)
{
if (node->relates())
node = node->relates();
- else if (!node->isInnerNode())
+ else if (!node->isInnerNode()) {
node = node->parent();
+#ifdef QDOC_QML
+ if (node->subType() == Node::QmlPropertyGroup) {
+ node = node->parent();
+ }
+#endif
+ }
QString base = node->doc().baseName();
if (!base.isEmpty())
return base;
- const Node *p = node;
-
- forever {
- base.prepend(p->name());
+ const Node *p = node;
+
+ forever {
+ base.prepend(p->name());
+#ifdef QDOC_QML
+ /*
+ To avoid file name conflicts in the html directory,
+ we prepend "qml-" to the file name of QML element doc
+ files.
+ */
+ if ((p->subType() == Node::QmlClass) ||
+ (p->subType() == Node::QmlPropertyGroup))
+ base.prepend("qml-");
+ else if ((p->type() == Node::QmlProperty) ||
+ (p->type() == Node::QmlSignal) ||
+ (p->type() == Node::QmlMethod))
+ base.prepend("qml-");
+#endif
const Node *pp = p->parent();
if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake)
- break;
+ break;
base.prepend(QLatin1Char('-'));
p = pp;
- }
-
- if (node->type() == Node::Fake) {
+ }
+
+ if (node->type() == Node::Fake) {
#ifdef QDOC2_COMPAT
- if (base.endsWith(".html"))
- base.truncate(base.length() - 5);
+ if (base.endsWith(".html"))
+ base.truncate(base.length() - 5);
#endif
- }
+ }
// the code below is effectively equivalent to:
// base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
@@ -126,7 +146,8 @@ QString PageGenerator::fileBase(const Node *node)
if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) {
res += QLatin1Char(u);
begun = true;
- } else if (begun) {
+ }
+ else if (begun) {
res += QLatin1Char('-');
begun = false;
}
@@ -187,8 +208,12 @@ void PageGenerator::generateInnerNode(const InnerNode *node,
if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
- if (fakeNode->subType() == FakeNode::ExternalPage)
+ if (fakeNode->subType() == Node::ExternalPage)
+ return;
+#ifdef QDOC_QML
+ if (fakeNode->subType() == Node::QmlPropertyGroup)
return;
+#endif
}
if (node->parent() != 0) {
@@ -197,12 +222,6 @@ void PageGenerator::generateInnerNode(const InnerNode *node,
generateClassLikeNode(node, marker);
}
else if (node->type() == Node::Fake) {
- const FakeNode* fakeNode = static_cast<const FakeNode *>(node);
-#ifdef QDOC_QML
- if (fakeNode->subType() == FakeNode::QmlClass) {
- //qDebug() << "FILENAME:" << fileName(node);
- }
-#endif
generateFakeNode(static_cast<const FakeNode *>(node), marker);
}
endSubPage();
diff --git a/tools/qdoc3/test/classic.css b/tools/qdoc3/test/classic.css
index fa0167b..e018dc6 100644
--- a/tools/qdoc3/test/classic.css
+++ b/tools/qdoc3/test/classic.css
@@ -185,3 +185,52 @@ span.string,span.char
{
font-size: 0.65em
}
+
+.qmlitem {
+ padding: 0;
+}
+
+.qmlname {
+ white-space: nowrap;
+ font-weight: bold;
+ font-size: 125%;
+}
+
+.qmltype {
+ font-weight: bold;
+ font-size: 125%;
+}
+
+.qmlproto, .qmldoc {
+ // border-top: 1px solid #84b0c7;
+}
+
+.qmlproto {
+ padding: 0;
+ //background-color: #e4e4e4;//#d5e1e8;
+ //font-weight: bold;
+ //-webkit-border-top-left-radius: 8px;
+ //-webkit-border-top-right-radius: 8px;
+ //-moz-border-radius-topleft: 8px;
+ //-moz-border-radius-topright: 8px;
+}
+
+.qmldoc {
+ border-top: 1px solid #e4e4e4;
+ //padding: 2px 5px;
+ //background-color: #eef3f5;
+ //border-top-width: 0;
+ //-webkit-border-bottom-left-radius: 8px;
+ //-webkit-border-bottom-right-radius: 8px;
+ //-moz-border-radius-bottomleft: 8px;
+ //-moz-border-radius-bottomright: 8px;
+}
+
+.qmldoc p, .qmldoc dl, .qmldoc ul {
+ //margin: 6px 0;
+}
+
+*.qmlitem p {
+ //margin-top: 0px;
+ //margin-bottom: 0px;
+}
diff --git a/tools/qdoc3/test/qml.qdocconf b/tools/qdoc3/test/qml.qdocconf
new file mode 100644
index 0000000..3a7d76a
--- /dev/null
+++ b/tools/qdoc3/test/qml.qdocconf
@@ -0,0 +1,77 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = Qml
+description = Qml Reference Documentation
+url = http://doc.qtsoftware.com/4.6
+
+edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \
+ QtXmlPatterns QtTest
+edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtSql QtSvg \
+ QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \
+ QtDesigner QtAssistant QAxContainer Phonon \
+ QAxServer QtUiTools QtTest QtDBus
+edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest
+edition.DesktopLight.groups = -graphicsview-api
+
+qhp.projects = Qml
+
+qhp.Qml.file = qml.qhp
+qhp.Qml.namespace = com.trolltech.qml.460
+qhp.Qml.virtualFolder = qdoc
+qhp.Qml.indexTitle = Qml Reference
+
+# Files not referenced in any qdoc file
+# See also extraimages.HTML
+qhp.Qml.extraFiles = classic.css \
+ images/qt-logo.png
+
+qhp.Qml.filterAttributes = qt 4.6.0 qtrefdoc
+qhp.Qml.customFilters.Qt.name = Qt 4.6.0
+qhp.Qml.customFilters.Qt.filterAttributes = qt 4.6.0
+qhp.Qml.subprojects = classes
+qhp.Qml.subprojects.classes.title = Elements
+qhp.Qml.subprojects.classes.indexTitle = Qml Elements
+qhp.Qml.subprojects.classes.selectors = fake:qmlclass
+qhp.Qml.subprojects.classes.sortPages = true
+
+language = Cpp
+
+headerdirs = $QT_SOURCE_TREE/src/declarative
+sourcedirs = $QT_SOURCE_TREE/src/declarative \
+ $QT_SOURCE_TREE/doc/src/declarative
+
+sources += $QT_SOURCE_TREE/doc/src/tutorials/declarative.qdoc
+
+sources.fileextensions = "*.cpp *.qdoc"
+examples.fileextensions = "*.cpp *.h *.js *.qml"
+
+exampledirs = $QT_SOURCE_TREE/doc/src \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/examples/tutorials \
+ $QT_SOURCE_TREE \
+ $QT_SOURCE_TREE/qmake/examples \
+ $QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs
+imagedirs = $QT_SOURCE_TREE/doc/src/images \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src/declarative/pics
+outputdir = $QT_BUILD_TREE/doc-build/html-qml
+tagfile = $QT_BUILD_TREE/doc-build/html-qml/qt.tags
+base = file:$QT_BUILD_TREE/doc/html-qml
+
+HTML.stylesheets = classic.css
+
+HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n" \
+ "<tr>\n" \
+ "<td align=\"left\" valign=\"top\">" \
+ "<img src=\"images/qt-logo.png\" align=\"left\" border=\"0\"/>" \
+ "</td>\n" \
+ "<td width=\"1\">&nbsp;&nbsp;</td>" \
+ "<td class=\"postheader\" valign=\"center\" align=\"left\">" \
+ "<a href=\"qmlreference.html\">" \
+ "<font color=\"#004faf\">Home</font></a>" \
+ "</td>\n" \
+ "</tr></table>"
diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf
index 3fbeb44..6e0253a 100644
--- a/tools/qdoc3/test/qt-build-docs.qdocconf
+++ b/tools/qdoc3/test/qt-build-docs.qdocconf
@@ -108,7 +108,8 @@ exampledirs = $QT_SOURCE_TREE/doc/src \
$QT_SOURCE_TREE/qmake/examples \
$QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs
imagedirs = $QT_SOURCE_TREE/doc/src/images \
- $QT_SOURCE_TREE/examples
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src/declarative/pics
outputdir = $QT_BUILD_TREE/doc/html
tagfile = $QT_BUILD_TREE/doc/html/qt.tags
base = file:$QT_BUILD_TREE/doc/html
diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf
index 107c692..7bde3fe 100644
--- a/tools/qdoc3/test/qt-cpp-ignore.qdocconf
+++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf
@@ -65,7 +65,9 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \
QT_BEGIN_INCLUDE_NAMESPACE \
QT_END_NAMESPACE \
QT_END_INCLUDE_NAMESPACE \
- PHONON_EXPORT
+ PHONON_EXPORT \
+ Q_DECLARATIVE_EXPORT \
+ Q_GADGET
Cpp.ignoredirectives = Q_DECLARE_HANDLE \
Q_DECLARE_INTERFACE \
Q_DECLARE_METATYPE \
diff --git a/tools/qdoc3/test/qt-inc.qdocconf b/tools/qdoc3/test/qt-inc.qdocconf
index d6cb0e6..88d4fcf 100644
--- a/tools/qdoc3/test/qt-inc.qdocconf
+++ b/tools/qdoc3/test/qt-inc.qdocconf
@@ -99,7 +99,9 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \
Q_TESTLIB_EXPORT \
Q_TYPENAME \
Q_XML_EXPORT \
- QDBUS_EXPORT
+ QDBUS_EXPORT \
+ Q_DECLARATIVE_EXPORT \
+ Q_GADGET
Cpp.ignoredirectives = Q_DECLARE_HANDLE \
Q_DECLARE_INTERFACE \
Q_DECLARE_METATYPE \
diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf
index 1ec9b72..e1ce8d3 100644
--- a/tools/qdoc3/test/qt.qdocconf
+++ b/tools/qdoc3/test/qt.qdocconf
@@ -110,7 +110,8 @@ exampledirs = $QTDIR/doc/src \
$QTDIR/qmake/examples \
$QTDIR/src/3rdparty/webkit/WebKit/qt/docs
imagedirs = $QTDIR/doc/src/images \
- $QTDIR/examples
+ $QTDIR/examples \
+ $QTDIR/doc/src/declarative/pics
outputdir = $QTDIR/doc/html
tagfile = $QTDIR/doc/html/qt.tags
base = file:$QTDIR/doc/html
diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp
index 0fbd438..b91de65 100644
--- a/tools/qdoc3/tree.cpp
+++ b/tools/qdoc3/tree.cpp
@@ -176,6 +176,8 @@ const Node *Tree::findNode(const QStringList &path,
}
/*!
+ Find the node with the specified \a path name of the
+ specified \a type.
*/
Node *Tree::findNode(const QStringList &path,
Node::Type type,
@@ -189,6 +191,8 @@ Node *Tree::findNode(const QStringList &path,
}
/*!
+ Find the node with the specified \a path name of the
+ specified \a type.
*/
const Node *Tree::findNode(const QStringList &path,
Node::Type type,
@@ -208,7 +212,9 @@ FunctionNode *Tree::findFunctionNode(const QStringList& path,
int findFlags)
{
return const_cast<FunctionNode *>(
- const_cast<const Tree *>(this)->findFunctionNode(path, relative, findFlags));
+ const_cast<const Tree *>(this)->findFunctionNode(path,
+ relative,
+ findFlags));
}
/*!
@@ -233,7 +239,8 @@ const FunctionNode *Tree::findFunctionNode(const QStringList &path,
else
next = ((InnerNode *) node)->findNode(path.at(i));
- if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
+ if (!next && node->type() == Node::Class &&
+ (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode *>(node));
foreach (const Node *baseClass, baseClasses) {
if (i == path.size() - 1)
@@ -563,7 +570,7 @@ void Tree::resolveGroups()
FakeNode *fake =
static_cast<FakeNode*>(findNode(QStringList(i.key()),Node::Fake));
- if (fake && fake->subType() == FakeNode::Group) {
+ if (fake && fake->subType() == Node::Group) {
fake->addGroupMember(i.value());
}
else {
@@ -770,21 +777,21 @@ void Tree::readIndexSection(const QDomElement &element,
}
else if (element.nodeName() == "page") {
- FakeNode::SubType subtype;
+ Node::SubType subtype;
if (element.attribute("subtype") == "example")
- subtype = FakeNode::Example;
+ subtype = Node::Example;
else if (element.attribute("subtype") == "header")
- subtype = FakeNode::HeaderFile;
+ subtype = Node::HeaderFile;
else if (element.attribute("subtype") == "file")
- subtype = FakeNode::File;
+ subtype = Node::File;
else if (element.attribute("subtype") == "group")
- subtype = FakeNode::Group;
+ subtype = Node::Group;
else if (element.attribute("subtype") == "module")
- subtype = FakeNode::Module;
+ subtype = Node::Module;
else if (element.attribute("subtype") == "page")
- subtype = FakeNode::Page;
+ subtype = Node::Page;
else if (element.attribute("subtype") == "externalpage")
- subtype = FakeNode::ExternalPage;
+ subtype = Node::ExternalPage;
else
return;
@@ -1226,25 +1233,25 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer,
const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
switch (fakeNode->subType()) {
- case FakeNode::Example:
+ case Node::Example:
writer.writeAttribute("subtype", "example");
break;
- case FakeNode::HeaderFile:
+ case Node::HeaderFile:
writer.writeAttribute("subtype", "header");
break;
- case FakeNode::File:
+ case Node::File:
writer.writeAttribute("subtype", "file");
break;
- case FakeNode::Group:
+ case Node::Group:
writer.writeAttribute("subtype", "group");
break;
- case FakeNode::Module:
+ case Node::Module:
writer.writeAttribute("subtype", "module");
break;
- case FakeNode::Page:
+ case Node::Page:
writer.writeAttribute("subtype", "page");
break;
- case FakeNode::ExternalPage:
+ case Node::ExternalPage:
writer.writeAttribute("subtype", "externalpage");
break;
default:
@@ -1383,7 +1390,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer,
bool external = false;
if (inner->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode *>(inner);
- if (fakeNode->subType() == FakeNode::ExternalPage)
+ if (fakeNode->subType() == Node::ExternalPage)
external = true;
}
@@ -1863,7 +1870,7 @@ void Tree::generateTagFile(const QString &fileName) const
*/
void Tree::addExternalLink(const QString &url, const Node *relative)
{
- FakeNode *fakeNode = new FakeNode(root(), url, FakeNode::ExternalPage);
+ FakeNode *fakeNode = new FakeNode(root(), url, Node::ExternalPage);
fakeNode->setAccess(Node::Public);
// Create some content for the node.
@@ -1895,9 +1902,13 @@ QString Tree::fullDocumentLocation(const Node *node) const
return "";
}
else if (node->type() == Node::Fake) {
+#ifdef QDOC_QML
+ if (node->subType() == Node::QmlClass)
+ return "qml-" + node->fileBase() + ".html";
+ else
+#endif
return node->fileBase() + ".html";
- }
- else if (node->fileBase().isEmpty())
+ } else if (node->fileBase().isEmpty())
return "";
QString parentName;
diff --git a/tools/qdoc3/webxmlgenerator.cpp b/tools/qdoc3/webxmlgenerator.cpp
index 0438adf..cf0995f 100644
--- a/tools/qdoc3/webxmlgenerator.cpp
+++ b/tools/qdoc3/webxmlgenerator.cpp
@@ -191,7 +191,7 @@ void WebXMLGenerator::generateIndexSections(QXmlStreamWriter &writer,
generateRelations(writer, node, marker);
- if (fake->subType() == FakeNode::Module) {
+ if (fake->subType() == Node::Module) {
writer.writeStartElement("generatedlist");
writer.writeAttribute("contents", "classesbymodule");
@@ -264,7 +264,7 @@ void WebXMLGenerator::generateInnerNode(const InnerNode *node, CodeMarker *marke
if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
- if (fakeNode->subType() == FakeNode::ExternalPage)
+ if (fakeNode->subType() == Node::ExternalPage)
return;
}
diff --git a/tools/qmldebugger/canvasframerate.cpp b/tools/qmldebugger/canvasframerate.cpp
new file mode 100644
index 0000000..022aed5
--- /dev/null
+++ b/tools/qmldebugger/canvasframerate.cpp
@@ -0,0 +1,304 @@
+#include "canvasframerate.h"
+#include <QtGui/qwidget.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qscrollbar.h>
+#include <QtDeclarative/qmldebugclient.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdatastream.h>
+#include <QtGui/qboxlayout.h>
+#include <QResizeEvent>
+#include <QShowEvent>
+#include <QTabWidget>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QCheckBox>
+
+class QLineGraph : public QWidget
+{
+Q_OBJECT
+public:
+ QLineGraph(QWidget * = 0);
+
+ void setPosition(int);
+
+public slots:
+ void addSample(int, int, int, int, bool);
+
+protected:
+ virtual void paintEvent(QPaintEvent *);
+ virtual QSize sizeHint() const;
+
+private slots:
+ void scrollbarChanged(int);
+
+private:
+ void updateScrollbar();
+ void drawSample(QPainter *, int, const QRect &);
+ void drawTime(QPainter *, const QRect &);
+ struct Sample {
+ int sample[4];
+ bool isBreak;
+ };
+ QList<Sample> _samples;
+
+ QScrollBar sb;
+ int position;
+ int samplesPerWidth;
+ int resolutionForHeight;
+ bool ignoreScroll;
+};
+
+QLineGraph::QLineGraph(QWidget *parent)
+: QWidget(parent), sb(Qt::Horizontal, this), position(-1), samplesPerWidth(99), resolutionForHeight(50), ignoreScroll(false)
+{
+ sb.setMaximum(0);
+ sb.setMinimum(0);
+ sb.setSingleStep(1);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ setLayout(layout);
+ layout->addStretch(2);
+ layout->addWidget(&sb);
+ QObject::connect(&sb, SIGNAL(valueChanged(int)), this, SLOT(scrollbarChanged(int)));
+}
+
+QSize QLineGraph::sizeHint() const
+{
+ return QSize(800, 600);
+}
+
+void QLineGraph::scrollbarChanged(int v)
+{
+ if(ignoreScroll)
+ return;
+
+ if (v == sb.maximum())
+ position = -1;
+ else
+ position = v;
+ update();
+}
+
+void QLineGraph::updateScrollbar()
+{
+ ignoreScroll = true;
+ sb.setMaximum(qMax(0, _samples.count() - samplesPerWidth - 1));
+
+ if(position == -1) {
+ sb.setValue(sb.maximum());
+ } else {
+ sb.setValue(position);
+ }
+ ignoreScroll = false;
+}
+
+void QLineGraph::addSample(int a, int b, int c, int d, bool isBreak)
+{
+ Sample s;
+ s.isBreak = isBreak;
+ s.sample[0] = a;
+ s.sample[1] = b;
+ s.sample[2] = c;
+ s.sample[3] = d;
+ _samples << s;
+ updateScrollbar();
+ update();
+}
+
+void QLineGraph::setPosition(int p)
+{
+ scrollbarChanged(p);
+}
+
+void QLineGraph::drawTime(QPainter *p, const QRect &rect)
+{
+ if(_samples.isEmpty())
+ return;
+
+ int first = position;
+ if(first == -1)
+ first = qMax(0, _samples.count() - samplesPerWidth - 1);
+ int last = qMin(_samples.count() - 1, first + samplesPerWidth);
+
+ qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth);
+
+ int t = 0;
+
+ for(int ii = first; ii <= last; ++ii) {
+ int sampleTime = _samples.at(ii).sample[3] / 1000;
+ if(sampleTime != t) {
+
+ int xEnd = rect.left() + scaleX * (ii - first);
+ p->drawLine(xEnd, rect.bottom(), xEnd, rect.bottom() + 7);
+
+ QRect text(xEnd - 30, rect.bottom() + 10, 60, 30);
+
+ p->drawText(text, Qt::AlignHCenter | Qt::AlignTop, QString::number(_samples.at(ii).sample[3]));
+
+ t = sampleTime;
+ }
+ }
+
+}
+
+void QLineGraph::drawSample(QPainter *p, int s, const QRect &rect)
+{
+ if(_samples.isEmpty())
+ return;
+
+ int first = position;
+ if(first == -1)
+ first = qMax(0, _samples.count() - samplesPerWidth - 1);
+ int last = qMin(_samples.count() - 1, first + samplesPerWidth);
+
+ qreal scaleY = rect.height() / resolutionForHeight;
+ qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth);
+
+ int xEnd;
+ int lastXEnd = rect.left();
+
+ p->save();
+ p->setPen(Qt::NoPen);
+ for(int ii = first + 1; ii <= last; ++ii) {
+
+ xEnd = rect.left() + scaleX * (ii - first);
+ int yEnd = rect.bottom() - _samples.at(ii).sample[s] * scaleY;
+
+ if (!(s == 0 && _samples.at(ii).isBreak))
+ p->drawRect(QRect(lastXEnd, yEnd, scaleX, _samples.at(ii).sample[s] * scaleY));
+
+ lastXEnd = xEnd;
+ }
+ p->restore();
+}
+
+void QLineGraph::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing);
+
+
+ QRect r(50, 10, width() - 60, height() - 60);
+ p.setBrush(QColor("lightsteelblue"));
+ drawSample(&p, 0, r);
+
+ p.setBrush(QColor("pink"));
+ drawSample(&p, 1, r);
+
+ p.setBrush(QColor("green"));
+ drawSample(&p, 2, r);
+
+ p.setBrush(Qt::NoBrush);
+ p.drawRect(r);
+
+ for(int ii = 0; ii <= resolutionForHeight; ++ii) {
+ int y = 1 + r.bottom() - ii * r.height() / resolutionForHeight;
+
+ if((ii % 10) == 0) {
+ p.drawLine(r.left() - 20, y, r.left(), y);
+ QRect text(r.left() - 20 - 53, y - 10, 50, 20);
+ p.drawText(text, Qt::AlignRight | Qt::AlignVCenter, QString::number(ii));
+ } else {
+ p.drawLine(r.left() - 7, y, r.left(), y);
+ }
+ }
+
+ drawTime(&p, r);
+}
+
+class CanvasFrameRatePlugin : public QmlDebugClientPlugin
+{
+Q_OBJECT
+public:
+ CanvasFrameRatePlugin(QmlDebugClient *client);
+
+signals:
+ void sample(int, int, int, int, bool);
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ int la;
+ int lb;
+ int ld;
+};
+
+CanvasFrameRatePlugin::CanvasFrameRatePlugin(QmlDebugClient *client)
+: QmlDebugClientPlugin(QLatin1String("CanvasFrameRate"), client), la(-1)
+{
+}
+
+void CanvasFrameRatePlugin::messageReceived(const QByteArray &data)
+{
+ QByteArray rwData = data;
+ QDataStream stream(&rwData, QIODevice::ReadOnly);
+
+ int a; int b; int c; int d; bool isBreak;
+ stream >> a >> b >> c >> d >> isBreak;
+
+ if (la != -1)
+ emit sample(c, lb, la, ld, isBreak);
+
+ la = a;
+ lb = b;
+ ld = d;
+}
+
+CanvasFrameRate::CanvasFrameRate(QmlDebugClient *client, QWidget *parent)
+: QWidget(parent)
+{
+ m_plugin = new CanvasFrameRatePlugin(client);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0,0,0,0);
+ layout->setSpacing(0);
+ setLayout(layout);
+
+ m_tabs = new QTabWidget(this);
+ layout->addWidget(m_tabs);
+
+ QHBoxLayout *bottom = new QHBoxLayout;
+ layout->addLayout(bottom);
+ bottom->addStretch(2);
+
+ QCheckBox *check = new QCheckBox("Enable", this);
+ bottom->addWidget(check);
+ QObject::connect(check, SIGNAL(stateChanged(int)),
+ this, SLOT(stateChanged(int)));
+
+ QPushButton *pb = new QPushButton(tr("New Tab"), this);
+ QObject::connect(pb, SIGNAL(clicked()), this, SLOT(newTab()));
+ bottom->addWidget(pb);
+
+ newTab();
+}
+
+void CanvasFrameRate::newTab()
+{
+ if (m_tabs->count()) {
+ QWidget *w = m_tabs->widget(m_tabs->count() - 1);
+ QObject::disconnect(m_plugin, SIGNAL(sample(int,int,int,int,bool)),
+ w, SLOT(addSample(int,int,int,int,bool)));
+ }
+
+ int id = m_tabs->count();
+
+ QLineGraph *graph = new QLineGraph(this);
+ QObject::connect(m_plugin, SIGNAL(sample(int,int,int,int,bool)),
+ graph, SLOT(addSample(int,int,int,int,bool)));
+
+ QString name = QLatin1String("Graph ") + QString::number(id);
+ m_tabs->addTab(graph, name);
+ m_tabs->setCurrentIndex(id);
+}
+
+void CanvasFrameRate::stateChanged(int s)
+{
+ bool checked = s != 0;
+
+ static_cast<QmlDebugClientPlugin *>(m_plugin)->setEnabled(checked);
+}
+
+#include "canvasframerate.moc"
diff --git a/tools/qmldebugger/canvasframerate.h b/tools/qmldebugger/canvasframerate.h
new file mode 100644
index 0000000..543f233
--- /dev/null
+++ b/tools/qmldebugger/canvasframerate.h
@@ -0,0 +1,24 @@
+#ifndef CANVASFRAMERATE_H
+#define CANVASFRAMERATE_H
+
+#include <QWidget>
+
+class QmlDebugClient;
+class QTabWidget;
+class CanvasFrameRate : public QWidget
+{
+ Q_OBJECT
+public:
+ CanvasFrameRate(QmlDebugClient *, QWidget *parent = 0);
+
+private slots:
+ void newTab();
+ void stateChanged(int);
+
+private:
+ QTabWidget *m_tabs;
+ QObject *m_plugin;
+};
+
+#endif // CANVASFRAMERATE_H
+
diff --git a/tools/qmldebugger/canvasscene.cpp b/tools/qmldebugger/canvasscene.cpp
new file mode 100644
index 0000000..2d5b764
--- /dev/null
+++ b/tools/qmldebugger/canvasscene.cpp
@@ -0,0 +1,245 @@
+#include "canvasscene.h"
+#include <QtDeclarative/qmldebugclient.h>
+#include <QDataStream>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QSpinBox>
+#include <QSplitter>
+#include <QtDeclarative/qfxrect.h>
+#include <QtDeclarative/qfximage.h>
+
+class CanvasSceneClientPlugin : public QmlDebugClientPlugin
+{
+public:
+ CanvasSceneClientPlugin(QmlDebugClient *, CanvasScene *s);
+
+protected:
+ void messageReceived(const QByteArray &);
+
+private:
+ void dump(QDataStream &, int indent);
+ CanvasScene *scene;
+};
+
+class QmlCanvasDebuggerItem : public QTreeWidgetItem
+{
+public:
+ QmlCanvasDebuggerItem(QTreeWidget *tree)
+ : QTreeWidgetItem(tree), me(0), img(0)
+ {
+ }
+
+ QmlCanvasDebuggerItem(QTreeWidgetItem *item)
+ : QTreeWidgetItem(item), me(0), img(0)
+ {
+ }
+
+ QFxRect *me;
+ QFxImage *img;
+};
+
+CanvasSceneClientPlugin::CanvasSceneClientPlugin(QmlDebugClient *c,
+ CanvasScene *s)
+: QmlDebugClientPlugin(QLatin1String("CanvasScene"), c), scene(s)
+{
+}
+
+void CanvasSceneClientPlugin::messageReceived(const QByteArray &data)
+{
+ QByteArray d = data;
+ QDataStream ds(&d, QIODevice::ReadOnly);
+
+ scene->message(ds);
+}
+
+void CanvasScene::message(QDataStream &ds)
+{
+ QList<QSimpleCanvasItem *> children = m_canvasRoot->children();
+ qDeleteAll(children);
+ m_tree->clear();
+ m_selected = 0;
+
+ QTreeWidgetItem *root = new QmlCanvasDebuggerItem(m_tree);
+ root->setText(0, tr("Root"));
+ root->setExpanded(true);
+ clone(root, m_canvasRoot, ds);
+}
+
+void CanvasScene::clone(QTreeWidgetItem *item, QSimpleCanvasItem *me,
+ QDataStream &ds)
+{
+ int children;
+ ds >> children;
+
+ for (int ii = 0; ii < children; ++ii) {
+ QString name;
+ qreal x, y, z, width, height, scale;
+ QTransform transform;
+ bool activeFocus;
+ int transformOrigin, flip, options;
+ QPixmap pix;
+
+ ds >> name >> x >> y >> z >> width >> height >> transformOrigin >> scale
+ >> flip >> transform >> activeFocus >> options >> pix;
+
+ QmlCanvasDebuggerItem *childItem = new QmlCanvasDebuggerItem(item);
+ childItem->setText(0, name);
+ childItem->setExpanded(true);
+
+ QFxRect *rect = new QFxRect;
+ rect->setParent(me);
+ rect->setX(x);
+ rect->setY(y);
+ rect->setZ(z);
+ rect->setWidth(width);
+ rect->setHeight(height);
+ rect->setTransformOrigin((QSimpleCanvasItem::TransformOrigin)transformOrigin);
+ rect->setScale(scale);
+ rect->setFlip((QSimpleCanvasItem::Flip)flip);
+ rect->setTransform(transform);
+
+ if (activeFocus)
+ rect->setColor(QColor(0, 0, 0, 10));
+ else if(options & QSimpleCanvasItem::IsFocusPanel)
+ rect->setColor(QColor(0, 255, 0, 10));
+ else if(options & QSimpleCanvasItem::IsFocusRealm)
+ rect->setColor(QColor(0, 0, 255, 10));
+ else
+ rect->setColor(QColor(255, 0, 0, 10));
+
+ if (pix.width() > 0 || pix.height() > 0) {
+ QFxImage *img = new QFxImage;
+ img->setParent(rect);
+ img->setWidth(width);
+ img->setHeight(height);
+ img->setPixmap(pix);
+ img->setOpacity(0);
+ childItem->img = img;
+ }
+
+ childItem->me = rect;
+
+ clone(childItem, rect, ds);
+ }
+}
+
+void CanvasSceneClientPlugin::dump(QDataStream &ds, int indent)
+{
+ QString name;
+ qreal x, y, z, width, height, scale;
+ QTransform transform;
+ bool activeFocus;
+ int transformOrigin, flip, options, count;
+ QPixmap pix;
+
+ ds >> name >> x >> y >> z >> width >> height >> transformOrigin >> scale
+ >> flip >> transform >> activeFocus >> options >> pix >> count;
+
+ QByteArray ba(indent * 4, ' ');
+ qWarning() << ba.constData() << name << x << y;
+
+ for(int ii = 0; ii < count; ++ii)
+ dump(ds, indent + 1);
+}
+
+CanvasScene::CanvasScene(QmlDebugClient *c, QWidget *parent)
+: QWidget(parent)
+{
+ client = new CanvasSceneClientPlugin(c, this);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0,0,0,0);
+ layout->setSpacing(0);
+ setLayout(layout);
+ QSplitter *splitter = new QSplitter(this);
+
+ m_tree = new QTreeWidget(this);
+ m_tree->setHeaderHidden(true);
+ QObject::connect(m_tree, SIGNAL(itemExpanded(QTreeWidgetItem*)),
+ this, SLOT(itemExpanded(QTreeWidgetItem*)));
+ QObject::connect(m_tree, SIGNAL(itemCollapsed(QTreeWidgetItem*)),
+ this, SLOT(itemCollapsed(QTreeWidgetItem*)));
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
+ this, SLOT(itemClicked(QTreeWidgetItem*)));
+ m_canvas = new QSimpleCanvas(QSimpleCanvas::SimpleCanvas, this);
+ m_canvasRoot = new QSimpleCanvasItem;
+ m_canvasRoot->setParent(m_canvas->root());
+ splitter->addWidget(m_tree);
+ splitter->addWidget(m_canvas);
+ splitter->setStretchFactor(1, 2);
+ layout->addWidget(splitter);
+
+ QHBoxLayout *hlayout = new QHBoxLayout;
+ hlayout->setContentsMargins(0,0,0,0);
+ hlayout->addStretch(2);
+ hlayout->setSpacing(0);
+ layout->addLayout(hlayout);
+ QSpinBox *x = new QSpinBox(this);
+ x->setSingleStep(50);
+ x->setMaximum(10000);
+ x->setMinimum(-10000);
+ QObject::connect(x, SIGNAL(valueChanged(int)), this, SLOT(setX(int)));
+ QSpinBox *y = new QSpinBox(this);
+ y->setSingleStep(50);
+ y->setMaximum(10000);
+ y->setMinimum(-10000);
+ QObject::connect(y, SIGNAL(valueChanged(int)), this, SLOT(setY(int)));
+ hlayout->addWidget(x);
+ hlayout->addWidget(y);
+ QPushButton *pb = new QPushButton(tr("Refresh"), this);
+ QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
+ hlayout->addWidget(pb);
+}
+
+void CanvasScene::refresh()
+{
+ client->sendMessage(QByteArray());
+}
+
+void CanvasScene::itemExpanded(QTreeWidgetItem *i)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+ if(item->me)
+ item->me->setOpacity(1);
+}
+
+void CanvasScene::setOpacityRecur(QTreeWidgetItem *i, qreal op)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+ if(item->img)
+ item->img->setOpacity(op);
+
+ for(int ii = 0; ii < item->childCount(); ++ii)
+ setOpacityRecur(item->child(ii), op);
+}
+
+void CanvasScene::itemClicked(QTreeWidgetItem *i)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+
+ if(m_selected) {
+ setOpacityRecur(m_selected, 0);
+ m_selected = 0;
+ }
+
+ m_selected = item;
+ setOpacityRecur(m_selected, 1);
+}
+
+void CanvasScene::itemCollapsed(QTreeWidgetItem *i)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+ if(item->me)
+ item->me->setOpacity(0);
+}
+
+void CanvasScene::setX(int x)
+{
+ m_canvasRoot->setX(x);
+}
+
+void CanvasScene::setY(int y)
+{
+ m_canvasRoot->setY(y);
+}
+
diff --git a/tools/qmldebugger/canvasscene.h b/tools/qmldebugger/canvasscene.h
new file mode 100644
index 0000000..d980241
--- /dev/null
+++ b/tools/qmldebugger/canvasscene.h
@@ -0,0 +1,39 @@
+#ifndef CANVASSCENE_H
+#define CANVASSCENE_H
+
+#include <QWidget>
+#include <QTreeWidget>
+#include <QtDeclarative/qsimplecanvas.h>
+#include <QtDeclarative/qsimplecanvasitem.h>
+
+class QmlDebugClient;
+class CanvasSceneClient;
+class QmlDebugClientPlugin;
+class CanvasScene : public QWidget
+{
+Q_OBJECT
+public:
+ CanvasScene(QmlDebugClient *, QWidget *parent = 0);
+
+ void message(QDataStream &);
+private slots:
+ void refresh();
+ void itemClicked(QTreeWidgetItem *);
+ void itemExpanded(QTreeWidgetItem *);
+ void itemCollapsed(QTreeWidgetItem *);
+ void setX(int);
+ void setY(int);
+
+private:
+ void setOpacityRecur(QTreeWidgetItem *, qreal);
+ void clone(QTreeWidgetItem *item, QSimpleCanvasItem *me, QDataStream &);
+ QmlDebugClientPlugin *client;
+
+ QTreeWidget *m_tree;
+ QSimpleCanvas *m_canvas;
+ QSimpleCanvasItem *m_canvasRoot;
+ QTreeWidgetItem *m_selected;
+};
+
+#endif // CANVASSCENE_H
+
diff --git a/tools/qmldebugger/main.cpp b/tools/qmldebugger/main.cpp
new file mode 100644
index 0000000..5b94cbb
--- /dev/null
+++ b/tools/qmldebugger/main.cpp
@@ -0,0 +1,137 @@
+#include <QtNetwork/qtcpsocket.h>
+#include <QtGui/qapplication.h>
+#include <QtGui/qwidget.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qscrollbar.h>
+#include <QtDeclarative/qmldebugclient.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdatastream.h>
+#include "canvasframerate.h"
+#include "canvasscene.h"
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QTabWidget>
+#include <QSpinBox>
+#include <QLabel>
+
+class Shell : public QWidget
+{
+Q_OBJECT
+public:
+ Shell(QWidget * = 0);
+
+private slots:
+ void connectToHost();
+ void disconnectFromHost();
+ void connectionStateChanged();
+
+private:
+ QmlDebugClient client;
+
+ QLabel *m_connectionState;
+ QLineEdit *m_host;
+ QSpinBox *m_port;
+ QPushButton *m_connectButton;
+ QPushButton *m_disconnectButton;
+};
+
+Shell::Shell(QWidget *parent)
+: QWidget(parent)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ setLayout(layout);
+
+
+ QHBoxLayout *connectLayout = new QHBoxLayout;
+ layout->addLayout(connectLayout);
+ connectLayout->addStretch(2);
+
+ m_connectionState = new QLabel(this);
+ connectLayout->addWidget(m_connectionState);
+ m_host = new QLineEdit(this);
+ m_host->setText("127.0.0.1");
+ connectLayout->addWidget(m_host);
+ m_port = new QSpinBox(this);
+ m_port->setMinimum(1024);
+ m_port->setMaximum(20000);
+ m_port->setValue(3768);
+ connectLayout->addWidget(m_port);
+ m_connectButton = new QPushButton(tr("Connect"), this);
+ QObject::connect(m_connectButton, SIGNAL(clicked()),
+ this, SLOT(connectToHost()));
+ connectLayout->addWidget(m_connectButton);
+ m_disconnectButton = new QPushButton(tr("Disconnect"), this);
+ QObject::connect(m_disconnectButton, SIGNAL(clicked()),
+ this, SLOT(disconnectFromHost()));
+ m_disconnectButton->setEnabled(false);
+ connectLayout->addWidget(m_disconnectButton);
+
+ QTabWidget *tabs = new QTabWidget(this);
+ layout->addWidget(tabs);
+
+ CanvasFrameRate *cfr = new CanvasFrameRate(&client, this);
+ tabs->addTab(cfr, tr("Frame Rate"));
+
+ CanvasScene *cs = new CanvasScene(&client, this);
+ tabs->addTab(cs, tr("Scene"));
+
+ QObject::connect(&client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(connectionStateChanged()));
+ connectionStateChanged();
+}
+
+void Shell::connectionStateChanged()
+{
+ switch (client.state()) {
+ default:
+ case QAbstractSocket::UnconnectedState:
+ m_connectionState->setText(tr("Disconnected"));
+ m_connectButton->setEnabled(true);
+ m_disconnectButton->setEnabled(false);
+ break;
+ case QAbstractSocket::HostLookupState:
+ m_connectionState->setText(tr("Resolving"));
+ m_connectButton->setEnabled(false);
+ m_disconnectButton->setEnabled(true);
+ break;
+ case QAbstractSocket::ConnectingState:
+ m_connectionState->setText(tr("Connecting"));
+ m_connectButton->setEnabled(false);
+ m_disconnectButton->setEnabled(true);
+ break;
+ case QAbstractSocket::ConnectedState:
+ m_connectionState->setText(tr("Connected"));
+ m_connectButton->setEnabled(false);
+ m_disconnectButton->setEnabled(true);
+ break;
+ case QAbstractSocket::ClosingState:
+ m_connectionState->setText(tr("Closing"));
+ m_connectButton->setEnabled(false);
+ m_disconnectButton->setEnabled(false);
+ break;
+ }
+}
+
+void Shell::connectToHost()
+{
+ client.connectToHost(m_host->text(), m_port->value());
+}
+
+void Shell::disconnectFromHost()
+{
+ client.disconnectFromHost();
+}
+
+int main(int argc, char ** argv)
+{
+ QApplication app(argc, argv);
+
+ Shell shell;
+ shell.show();
+
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/tools/qmldebugger/qmldebugger.pro b/tools/qmldebugger/qmldebugger.pro
new file mode 100644
index 0000000..757ba12
--- /dev/null
+++ b/tools/qmldebugger/qmldebugger.pro
@@ -0,0 +1,10 @@
+DESTDIR = ../../bin
+QT += network declarative
+# Input
+HEADERS += canvasframerate.h canvasscene.h
+SOURCES += main.cpp canvasframerate.cpp canvasscene.cpp
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+CONFIG += console
diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp
new file mode 100644
index 0000000..ed700a0
--- /dev/null
+++ b/tools/qmlviewer/main.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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 "qml.h"
+#include "qmlviewer.h"
+#include <QWidget>
+#include <QDir>
+#include "qfxtestengine.h"
+#include <QApplication>
+#include <QTranslator>
+#include <QDebug>
+
+void usage()
+{
+ qWarning("Usage: qmlviewer [options] <filename>");
+ qWarning(" ");
+ qWarning(" options:");
+ qWarning(" -v, -version ............................. display version");
+ qWarning(" -frameless ............................... run with no window frame");
+ qWarning(" -skin <qvfbskindir> ...................... run with a skin window frame");
+ qWarning(" -recordfile <output> ..................... set video recording file");
+ qWarning(" - ImageMagick 'convert' for GIF)");
+ qWarning(" - png file for raw frames");
+ qWarning(" - 'ffmpeg' for other formats");
+ qWarning(" -recorddither ordered|threshold|floyd .... set GIF dither recording mode");
+ qWarning(" -recordperiod <milliseconds> ............. set time between recording frames");
+ qWarning(" -record arg .............................. add a recording process argument");
+ qWarning(" -autorecord [from-]<tomilliseconds> ...... set recording to start and stop");
+ qWarning(" -devicekeys .............................. use numeric keys (see F1)");
+ qWarning(" -cache ................................... disk cache remote content");
+ qWarning(" -recordtest <directory> .................. record an autotest");
+ qWarning(" -runtest <directory> ..................... run a previously recorded test");
+ qWarning(" -translation <translationfile> ........... set the language to run in");
+ qWarning(" -L <directory> ........................... prepend to the library search path");
+ qWarning(" ");
+ qWarning(" Press F1 for interactive help");
+ exit(1);
+}
+
+int main(int argc, char ** argv)
+{
+ //### default to using raster graphics backend for now
+ bool gsSpecified = false;
+ for (int i = 0; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-graphicssystem") {
+ gsSpecified = true;
+ break;
+ }
+ }
+ if (!gsSpecified)
+ QApplication::setGraphicsSystem("raster");
+
+ QApplication app(argc, argv);
+ app.setApplicationName("viewer");
+
+ bool frameless = false;
+ QString fileName;
+ int period = 0;
+ int autorecord_from = 0;
+ int autorecord_to = 0;
+ QString dither = "none";
+ QString recordfile;
+ QStringList recordargs;
+ QStringList libraries;
+ QString skin;
+ bool devkeys = false;
+ bool cache = false;
+ QFxTestEngine::TestMode testMode = QFxTestEngine::NoTest;
+ QString testDir;
+ QString translationFile;
+
+ for (int i = 1; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-frameless") {
+ frameless = true;
+ } else if (arg == "-skin") {
+ skin = QString(argv[++i]);
+ } else if (arg == "-cache") {
+ cache = true;
+ } else if (arg == "-recordperiod") {
+ period = QString(argv[++i]).toInt();
+ } else if (arg == "-recordfile") {
+ recordfile = QString(argv[++i]);
+ } else if (arg == "-record") {
+ recordargs << QString(argv[++i]);
+ } else if (arg == "-recorddither") {
+ dither = QString(argv[++i]);
+ } else if (arg == "-autorecord") {
+ QString range = QString(argv[++i]);
+ int dash = range.indexOf('-');
+ if (dash > 0)
+ autorecord_from = range.left(dash).toInt();
+ autorecord_to = range.mid(dash+1).toInt();
+ } else if (arg == "-devicekeys") {
+ devkeys = true;
+ } else if (arg == "-recordtest") {
+ testMode = QFxTestEngine::RecordTest;
+ if(i + 1 >= argc)
+ usage();
+ testDir = argv[i + 1];
+ ++i;
+ } else if (arg == "-runtest") {
+ testMode = QFxTestEngine::PlaybackTest;
+ if(i + 1 >= argc)
+ usage();
+ testDir = argv[i + 1];
+ ++i;
+ } else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) {
+ fprintf(stderr, "Qt Declarative UI Viewer version %s\n", QT_VERSION_STR);
+ return 0;
+ } else if (arg == "-translation") {
+ if(i + 1 >= argc)
+ usage();
+ translationFile = argv[i + 1];
+ ++i;
+ } else if (arg == "-L") {
+ libraries << QString(argv[++i]);
+ } else if (arg[0] != '-') {
+ fileName = arg;
+ } else if (1 || arg == "-help") {
+ usage();
+ }
+ }
+
+ QTranslator qmlTranslator;
+ if (!translationFile.isEmpty()) {
+ qmlTranslator.load(translationFile);
+ app.installTranslator(&qmlTranslator);
+ }
+
+ QmlViewer viewer(testMode, testDir, 0, frameless ? Qt::FramelessWindowHint : Qt::Widget);
+ foreach (QString lib, libraries)
+ viewer.addLibraryPath(lib);
+ viewer.setCacheEnabled(cache);
+ viewer.setRecordFile(recordfile);
+ if (period>0)
+ viewer.setRecordPeriod(period);
+ if (autorecord_to)
+ viewer.setAutoRecord(autorecord_from,autorecord_to);
+ if (!skin.isEmpty() && QDir(skin).exists())
+ viewer.setSkin(skin);
+ if (devkeys)
+ viewer.setDeviceKeys(true);
+ viewer.setRecordDither(dither);
+ viewer.setRecordArgs(recordargs);
+ if (!fileName.isEmpty())
+ viewer.openQml(fileName);
+ else
+ viewer.open();
+ viewer.show();
+
+ return app.exec();
+}
+
diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp
new file mode 100644
index 0000000..75a8f1c
--- /dev/null
+++ b/tools/qmlviewer/qmlviewer.cpp
@@ -0,0 +1,696 @@
+/****************************************************************************
+**
+** 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 <qfxview.h>
+
+#include "qmlbindablevalue.h"
+#include "qmlviewer.h"
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#include "qml.h"
+#include "qperformancelog.h"
+#include "qfxtestengine.h"
+#include "deviceskin.h"
+
+#include <QNetworkDiskCache>
+#include <QNetworkAccessManager>
+#include <QSignalMapper>
+#include <QmlComponent>
+#include <QWidget>
+#include <QApplication>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QVBoxLayout>
+#include <QProgressDialog>
+#include <QProcess>
+#include <QMenuBar>
+#include <QMenu>
+#include <QAction>
+#include <QFileDialog>
+#include <QTimer>
+
+class PreviewDeviceSkin : public DeviceSkin
+{
+ Q_OBJECT
+public:
+ explicit PreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent);
+
+ void setPreview(QWidget *formWidget);
+ void setPreviewAndScale(QWidget *formWidget);
+
+ void setScreenSize(const QSize& size)
+ {
+ QMatrix fit;
+ fit = fit.scale(qreal(size.width())/m_screenSize.width(),
+ qreal(size.height())/m_screenSize.height());
+ setTransform(fit);
+ QApplication::syncX();
+ }
+
+ QSize standardScreenSize() const { return m_screenSize; }
+
+ QMenu* menu;
+
+private slots:
+ void slotSkinKeyPressEvent(int code, const QString& text, bool autorep);
+ void slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep);
+ void slotPopupMenu();
+
+private:
+ const QSize m_screenSize;
+};
+
+
+PreviewDeviceSkin::PreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent) :
+ DeviceSkin(parameters, parent),
+ m_screenSize(parameters.screenSize())
+{
+ menu = new QMenu(this);
+ connect(this, SIGNAL(skinKeyPressEvent(int,QString,bool)),
+ this, SLOT(slotSkinKeyPressEvent(int,QString,bool)));
+ connect(this, SIGNAL(skinKeyReleaseEvent(int,QString,bool)),
+ this, SLOT(slotSkinKeyReleaseEvent(int,QString,bool)));
+ connect(this, SIGNAL(popupMenu()), this, SLOT(slotPopupMenu()));
+}
+
+void PreviewDeviceSkin::setPreview(QWidget *formWidget)
+{
+ formWidget->setFixedSize(m_screenSize);
+ formWidget->setParent(this, Qt::SubWindow);
+ formWidget->setAutoFillBackground(true);
+ setView(formWidget);
+}
+
+void PreviewDeviceSkin::setPreviewAndScale(QWidget *formWidget)
+{
+ setScreenSize(formWidget->sizeHint());
+ formWidget->setParent(this, Qt::SubWindow);
+ formWidget->setAutoFillBackground(true);
+ setView(formWidget);
+}
+
+void PreviewDeviceSkin::slotSkinKeyPressEvent(int code, const QString& text, bool autorep)
+{
+ if (QWidget *focusWidget = QApplication::focusWidget()) {
+ QKeyEvent e(QEvent::KeyPress,code,0,text,autorep);
+ QApplication::sendEvent(focusWidget, &e);
+ }
+
+}
+
+void PreviewDeviceSkin::slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep)
+{
+ if (QWidget *focusWidget = QApplication::focusWidget()) {
+ QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep);
+ QApplication::sendEvent(focusWidget, &e);
+ }
+}
+
+void PreviewDeviceSkin::slotPopupMenu()
+{
+ menu->exec(QCursor::pos());
+}
+
+
+QmlViewer::QmlViewer(QFxTestEngine::TestMode testMode, const QString &testDir, QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags), frame_stream(0), scaleSkin(true), mb(0)
+{
+ testEngine = 0;
+ devicemode = false;
+ skin = 0;
+ canvas = 0;
+ record_autotime = 0;
+ record_period = 20;
+
+ if (!(flags & Qt::FramelessWindowHint))
+ createMenu(menuBar(),0);
+
+ canvas = new QFxView(this);
+ canvas->setAttribute(Qt::WA_OpaquePaintEvent);
+ canvas->setAttribute(Qt::WA_NoSystemBackground);
+ canvas->setContentResizable(!skin || !scaleSkin);
+
+ if(testMode != QFxTestEngine::NoTest)
+ testEngine = new QFxTestEngine(testMode, testDir, canvas, this);
+
+ QObject::connect(canvas, SIGNAL(sceneResized(QSize)), this, SLOT(sceneResized(QSize)));
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ setLayout(layout);
+ if (mb)
+ layout->addWidget(mb);
+ layout->addWidget(canvas);
+}
+
+QMenuBar *QmlViewer::menuBar() const
+{
+ if (!mb)
+ mb = new QMenuBar((QWidget*)this);
+
+ return mb;
+}
+
+void QmlViewer::createMenu(QMenuBar *menu, QMenu *flatmenu)
+{
+ QObject *parent = flatmenu ? (QObject*)flatmenu : (QObject*)menu;
+
+ QMenu *fileMenu = flatmenu ? flatmenu : menu->addMenu(tr("&File"));
+
+ QAction *openAction = new QAction(tr("&Open..."), parent);
+ openAction->setShortcut(QKeySequence("Ctrl+O"));
+ connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
+ fileMenu->addAction(openAction);
+
+ QAction *reloadAction = new QAction(tr("&Reload"), parent);
+ reloadAction->setShortcut(QKeySequence("Ctrl+R"));
+ connect(reloadAction, SIGNAL(triggered()), this, SLOT(reload()));
+ fileMenu->addAction(reloadAction);
+
+ if (flatmenu) flatmenu->addSeparator();
+
+ QMenu *recordMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Recording"));
+
+ QAction *snapshotAction = new QAction(tr("&Take Snapsot\tF3"), parent);
+ connect(snapshotAction, SIGNAL(triggered()), this, SLOT(takeSnapShot()));
+ recordMenu->addAction(snapshotAction);
+
+ recordAction = new QAction(tr("Start Recording &Video\tF2"), parent);
+ connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection()));
+ recordMenu->addAction(recordAction);
+
+ if (flatmenu) flatmenu->addSeparator();
+
+ QMenu *skinMenu = flatmenu ? flatmenu->addMenu(tr("&Skin")) : menu->addMenu(tr("&Skin"));
+
+ QActionGroup *skinActions;
+ QAction *skinAction;
+
+ skinActions = new QActionGroup(parent);
+ skinAction = new QAction(tr("Scale skin"), parent);
+ skinAction->setCheckable(true);
+ skinAction->setChecked(scaleSkin);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ connect(skinAction, SIGNAL(triggered()), this, SLOT(setScaleSkin()));
+ skinAction = new QAction(tr("Scale view"), parent);
+ skinAction->setCheckable(true);
+ skinAction->setChecked(!scaleSkin);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ connect(skinAction, SIGNAL(triggered()), this, SLOT(setScaleView()));
+ skinMenu->addSeparator();
+
+ skinActions = new QActionGroup(parent);
+ QSignalMapper *mapper = new QSignalMapper(parent);
+ skinAction = new QAction(tr("None"), parent);
+ skinAction->setCheckable(true);
+ if (currentSkin.isEmpty())
+ skinAction->setChecked(true);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ mapper->setMapping(skinAction, "");
+ connect(skinAction, SIGNAL(triggered()), mapper, SLOT(map()));
+ skinMenu->addSeparator();
+
+ QDir dir(":/skins/","*.skin");
+ const QFileInfoList l = dir.entryInfoList();
+ for (QFileInfoList::const_iterator it = l.begin(); it != l.end(); ++it) {
+ QString name = (*it).baseName(); // should perhaps be in file
+ QString file = (*it).filePath();
+ skinAction = new QAction(name, parent);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ skinAction->setCheckable(true);
+ if (file == currentSkin)
+ skinAction->setChecked(true);
+ mapper->setMapping(skinAction, file);
+ connect(skinAction, SIGNAL(triggered()), mapper, SLOT(map()));
+ }
+ //connect(skinActions, SIGNAL(triggered(QAction*)), mapper, SLOT(map(QObject*))); // "incompatible"
+ connect(mapper, SIGNAL(mapped(QString)), this, SLOT(setSkin(QString)));
+
+ if (flatmenu) flatmenu->addSeparator();
+
+ QMenu *helpMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Help"));
+ QAction *aboutAction = new QAction(tr("&About Qt..."), parent);
+ connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ helpMenu->addAction(aboutAction);
+
+ QAction *quitAction = new QAction(tr("&Quit"), parent);
+ quitAction->setShortcut(QKeySequence("Ctrl+Q"));
+ connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ fileMenu->addSeparator();
+ fileMenu->addAction(quitAction);
+ if (menu) {
+ menu->setFixedHeight(menu->sizeHint().height());
+ menu->setMinimumWidth(10);
+ }
+}
+
+void QmlViewer::setScaleSkin()
+{
+ if (scaleSkin)
+ return;
+ scaleSkin = true;
+ canvas->setContentResizable(!skin || !scaleSkin);
+ if (skin) {
+ canvas->setFixedSize(canvas->sizeHint());
+ skin->setScreenSize(canvas->sizeHint());
+ }
+}
+
+void QmlViewer::setScaleView()
+{
+ if (!scaleSkin)
+ return;
+ scaleSkin = false;
+ if (skin) {
+ canvas->setContentResizable(!skin || !scaleSkin);
+ canvas->setMinimumSize(QSize(0,0));
+ canvas->setMaximumSize(QSize(16777215,16777215));
+ canvas->resize(skin->standardScreenSize());
+ skin->setScreenSize(skin->standardScreenSize());
+ }
+}
+
+
+void QmlViewer::takeSnapShot()
+{
+ static int snapshotcount = 1;
+ QString snapFileName = QString(QLatin1String("snapshot%1.png")).arg(snapshotcount);
+ canvas->asImage().save(snapFileName);
+ qDebug() << "Wrote" << snapFileName;
+ ++snapshotcount;
+}
+
+void QmlViewer::toggleRecordingWithSelection()
+{
+ if (!recordTimer.isActive()) {
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save Video File"), "", tr("Common Video files (*.avi *.mpeg *.mov);; GIF Animation (*.gif);; Individual PNG frames (*.png);; All ffmpeg formats (*.*)"));
+ if (fileName.isEmpty())
+ return;
+ if (!fileName.contains(QRegExp(".[^\\/]*$")))
+ fileName += ".avi";
+ setRecordFile(fileName);
+ }
+ toggleRecording();
+}
+
+void QmlViewer::toggleRecording()
+{
+ if (record_file.isEmpty()) {
+ toggleRecordingWithSelection();
+ return;
+ }
+ bool recording = !recordTimer.isActive();
+ recordAction->setText(recording ? tr("&Stop Recording Video\tF2") : tr("&Start Recording Video\tF2"));
+ setRecording(recording);
+}
+
+void QmlViewer::addLibraryPath(const QString& lib)
+{
+ canvas->engine()->addNameSpacePath("",lib);
+}
+
+void QmlViewer::reload()
+{
+ openQml(currentFileName);
+}
+
+void QmlViewer::open()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open QML file"), "", tr("QML Files (*.qml)"));
+ if (!fileName.isEmpty()) {
+ openQml(fileName);
+ QTimer::singleShot(0, this, SLOT(reload()));
+ }
+}
+
+void QmlViewer::openQml(const QString& fileName)
+{
+ setWindowTitle(tr("%1 - Qt Declarative UI Viewer").arg(fileName));
+
+ canvas->reset();
+
+ currentFileName = fileName;
+ QUrl url(fileName);
+ QFileInfo fi(fileName);
+ if (fi.exists()) {
+ url = QUrl::fromLocalFile(fi.absoluteFilePath());
+ QmlContext *ctxt = canvas->rootContext();
+ QDir dir(fi.path()+"/dummydata", "*.qml");
+ QStringList list = dir.entryList();
+ for (int i = 0; i < list.size(); ++i) {
+ QString qml = list.at(i);
+ QFile f(dir.filePath(qml));
+ f.open(QIODevice::ReadOnly);
+ QByteArray data = f.readAll();
+ QmlComponent comp(canvas->engine());
+ comp.setData(data, QUrl());
+ QObject *dummyData = comp.create();
+
+ if(comp.isError()) {
+ QList<QmlError> errors = comp.errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+ }
+
+ if (dummyData) {
+ qWarning() << "Loaded dummy data:" << dir.filePath(qml);
+ qml.truncate(qml.length()-4);
+ ctxt->setContextProperty(qml, dummyData);
+ dummyData->setParent(this);
+ }
+ }
+ }
+
+ canvas->setUrl(url);
+
+ QTime t;
+ t.start();
+ canvas->execute();
+ qWarning() << "Wall startup time:" << t.elapsed();
+
+ if (!skin) {
+ canvas->resize(canvas->sizeHint());
+ resize(sizeHint());
+ } else {
+ if (scaleSkin)
+ canvas->resize(canvas->sizeHint());
+ else {
+ canvas->setFixedSize(skin->standardScreenSize());
+ canvas->resize(skin->standardScreenSize());
+ }
+ }
+
+#ifdef QTOPIA
+ show();
+#endif
+}
+
+
+void QmlViewer::setSkin(const QString& skinDirectory)
+{
+ // XXX QWidget::setMask does not handle changes well, and we may
+ // XXX have been signalled from an item in a menu we're replacing,
+ // XXX hence some rather convoluted resetting here...
+
+ if (currentSkin == skinDirectory)
+ return;
+
+ currentSkin = skinDirectory;
+
+ QString err;
+ if (skin) {
+ skin->hide();
+ skin->deleteLater();
+ }
+
+ canvas->setContentResizable(!skin || !scaleSkin);
+
+ DeviceSkinParameters parameters;
+ if (!skinDirectory.isEmpty() && parameters.read(skinDirectory,DeviceSkinParameters::ReadAll,&err)) {
+ layout()->setEnabled(false);
+ //setMenuBar(0);
+ if (mb)
+ mb->hide();
+ if (!err.isEmpty())
+ qWarning() << err;
+ skin = new PreviewDeviceSkin(parameters,this);
+ canvas->resize(canvas->sizeHint());
+ if (scaleSkin)
+ skin->setPreviewAndScale(canvas);
+ else
+ skin->setPreview(canvas);
+ createMenu(0,skin->menu);
+ skin->show();
+ } else {
+ skin = 0;
+ clearMask();
+ menuBar()->clear();
+ canvas->setParent(this, Qt::SubWindow);
+ createMenu(menuBar(),0);
+ mb->show();
+ setMinimumSize(QSize(0,0));
+ setMaximumSize(QSize(16777215,16777215));
+ canvas->setMinimumSize(QSize(0,0));
+ canvas->setMaximumSize(QSize(16777215,16777215));
+ QRect g = geometry();
+ g.setSize(sizeHint());
+ setParent(0,windowFlags()); // recreate
+ canvas->move(0,menuBar()->sizeHint().height());
+ setGeometry(g);
+ layout()->setEnabled(true);
+ show();
+ }
+ canvas->show();
+}
+
+void QmlViewer::setAutoRecord(int from, int to)
+{
+ record_autotime = to-from;
+ if (from) {
+ autoStartTimer.start(from,this);
+ } else {
+ autoTimer.start();
+ setRecording(true);
+ }
+}
+
+void QmlViewer::setRecordArgs(const QStringList& a)
+{
+ record_args = a;
+}
+
+void QmlViewer::setRecordFile(const QString& f)
+{
+ record_file = f;
+}
+
+void QmlViewer::setRecordPeriod(int ms)
+{
+ record_period = ms;
+}
+
+void QmlViewer::sceneResized(QSize size)
+{
+ if (size.width() > 0 && size.height() > 0) {
+ if (skin && scaleSkin)
+ skin->setScreenSize(size);
+ }
+}
+
+void QmlViewer::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_0 && devicemode)
+ exit(0);
+ else if (event->key() == Qt::Key_F1 || (event->key() == Qt::Key_1 && devicemode)) {
+ qDebug() << "F1 - help\n"
+ << "F2 - toggle video recording\n"
+ << "F3 - take PNG snapshot\n"
+ << "F4 - show items and state\n"
+ << "F5 - reload QML\n"
+ << "F6 - show object tree\n"
+ << "F7 - show timing\n"
+ << "F8 - show performance (if available)\n"
+ << "device keys: 0=quit, 1..8=F1..F8"
+ ;
+ } else if (event->key() == Qt::Key_F2 || (event->key() == Qt::Key_2 && devicemode)) {
+ toggleRecording();
+ } else if (event->key() == Qt::Key_F3 || (event->key() == Qt::Key_3 && devicemode)) {
+ takeSnapShot();
+ } else if (event->key() == Qt::Key_F4 || (event->key() == Qt::Key_4 && devicemode)) {
+ canvas->dumpItems();
+ canvas->checkState();
+ } else if (event->key() == Qt::Key_F5 || (event->key() == Qt::Key_5 && devicemode)) {
+ reload();
+ } else if (event->key() == Qt::Key_F6 || (event->key() == Qt::Key_6 && devicemode)) {
+ canvas->dumpRoot();
+ } else if (event->key() == Qt::Key_F7 || (event->key() == Qt::Key_7 && devicemode)) {
+ canvas->dumpTiming();
+ } else if (event->key() == Qt::Key_F8 || (event->key() == Qt::Key_8 && devicemode)) {
+ QPerformanceLog::displayData();
+ QPerformanceLog::clear();
+ } else if (event->key() == Qt::Key_F9) {
+ if(testEngine) testEngine->save();
+ } else if (event->key() == Qt::Key_F10) {
+ if(testEngine) testEngine->captureFullFrame();
+ }
+
+ QWidget::keyPressEvent(event);
+}
+
+void QmlViewer::setRecording(bool on)
+{
+ if (on == recordTimer.isActive())
+ return;
+
+ if (on) {
+ recordTimer.start(record_period,this);
+ QString fmt = record_file.right(4).toLower();
+ if (fmt != ".png" && fmt != ".gif") {
+ // Stream video to ffmpeg
+
+ QProcess *proc = new QProcess(this);
+ connect(proc, SIGNAL(finished(int)), this, SLOT(ffmpegFinished(int)));
+ frame_stream = proc;
+
+ QStringList args;
+ args << "-sameq"; // ie. high
+ args << "-y";
+ args << "-r" << QString::number(1000/record_period);
+ args << "-f" << "rawvideo";
+ args << "-pix_fmt" << "rgb32";
+ args << "-s" << QString("%1x%2").arg(canvas->width()).arg(canvas->height());
+ args << "-i" << "-";
+ args += record_args;
+ args << record_file;
+ proc->start("ffmpeg",args);
+
+ } else {
+ // Store frames, save to GIF/PNG
+ frame_stream = 0;
+ }
+ } else {
+ recordTimer.stop();
+ if (frame_stream) {
+ qDebug() << "Saving video...";
+ frame_stream->close();
+ qDebug() << "Wrote" << record_file;
+ } else {
+ QProgressDialog progress(tr("Saving frames..."), tr("Cancel"), 0, frames.count()+10, this);
+ progress.setWindowModality(Qt::WindowModal);
+
+ int frame=0;
+ QStringList inputs;
+ qDebug() << "Saving frames...";
+
+ QString framename;
+ bool png_output = false;
+ if (record_file.right(4).toLower()==".png") {
+ if (record_file.contains('%'))
+ framename = record_file;
+ else
+ framename = record_file.left(record_file.length()-4)+"%04d"+record_file.right(4);
+ png_output = true;
+ } else {
+ framename = "tmp-frame%04d.png";
+ png_output = false;
+ }
+ foreach (QImage* img, frames) {
+ progress.setValue(progress.value()+1);
+ if (progress.wasCanceled())
+ break;
+ QString name;
+ name.sprintf(framename.toLocal8Bit(),frame++);
+ if (record_dither=="ordered")
+ img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::OrderedDither).save(name);
+ else if (record_dither=="threshold")
+ img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::ThresholdDither).save(name);
+ else if (record_dither=="floyd")
+ img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither).save(name);
+ else
+ img->save(name);
+ inputs << name;
+ delete img;
+ }
+
+ if (!progress.wasCanceled()) {
+ if (png_output) {
+ framename.replace(QRegExp("%\\d*."),"*");
+ qDebug() << "Wrote frames" << framename;
+ inputs.clear(); // don't remove them
+ } else {
+ // ImageMagick and gifsicle for GIF encoding
+ progress.setLabelText(tr("Converting frames to GIF file..."));
+ QStringList args;
+ args << "-delay" << QString::number(record_period/10);
+ args << inputs;
+ args << record_file;
+ qDebug() << "Converting..." << record_file << "(this may take a while)";
+ if (0!=QProcess::execute("convert", args)) {
+ qWarning() << "Cannot run ImageMagick 'convert' - recorded frames not converted";
+ inputs.clear(); // don't remove them
+ qDebug() << "Wrote frames tmp-frame*.png";
+ } else {
+ if (record_file.right(4).toLower() == ".gif") {
+ qDebug() << "Compressing..." << record_file;
+ if (0!=QProcess::execute("gifsicle", QStringList() << "-O2" << "-o" << record_file << record_file))
+ qWarning() << "Cannot run 'gifsicle' - not compressed";
+ }
+ qDebug() << "Wrote" << record_file;
+ }
+ }
+ }
+
+ progress.setValue(progress.maximum()-1);
+ foreach (QString name, inputs)
+ QFile::remove(name);
+
+ frames.clear();
+ }
+ }
+ qDebug() << "Recording: " << (recordTimer.isActive()?"ON":"OFF");
+}
+
+void QmlViewer::ffmpegFinished(int code)
+{
+ qDebug() << "ffmpeg returned" << code << frame_stream->readAllStandardError();
+}
+
+void QmlViewer::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == recordTimer.timerId()) {
+ if (frame_stream) {
+ QImage frame(canvas->asImage());
+ frame_stream->write((char*)frame.bits(),frame.numBytes());
+ } else {
+ frames.append(new QImage(canvas->asImage()));
+ }
+ if (record_autotime && autoTimer.elapsed() >= record_autotime)
+ setRecording(false);
+ } else if (event->timerId() == autoStartTimer.timerId()) {
+ autoTimer.start();
+ autoStartTimer.stop();
+ setRecording(true);
+ } else {
+ QWidget::timerEvent(event);
+ }
+}
+
+void QmlViewer::setDeviceKeys(bool on)
+{
+ devicemode = on;
+}
+
+void QmlViewer::setCacheEnabled(bool on)
+{
+ QNetworkAccessManager * nam = canvas->engine()->networkAccessManager();
+ if (on == !!nam->cache())
+ return;
+ if (on) {
+ // Setup a caching network manager
+ QNetworkDiskCache *cache = new QNetworkDiskCache;
+ cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-duiviewer-network-cache"));
+ cache->setMaximumCacheSize(8000000);
+ nam->setCache(cache);
+ } else {
+ nam->setCache(0);
+ }
+}
+
+#include "qmlviewer.moc"
diff --git a/tools/qmlviewer/qmlviewer.h b/tools/qmlviewer/qmlviewer.h
new file mode 100644
index 0000000..45ec446
--- /dev/null
+++ b/tools/qmlviewer/qmlviewer.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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 QMLVIEWER_H
+#define QMLVIEWER_H
+
+#include <QMenuBar>
+#include <QBasicTimer>
+#include <QTime>
+#include <qfxtestengine.h>
+#include <QList>
+
+
+class QFxView;
+class PreviewDeviceSkin;
+class QFxTestEngine;
+class QProcess;
+
+class QmlViewer : public QWidget
+{
+Q_OBJECT
+public:
+ QmlViewer(QFxTestEngine::TestMode = QFxTestEngine::NoTest, const QString &testDir = QString(), QWidget *parent=0, Qt::WindowFlags flags=0);
+
+ void setRecordDither(const QString& s) { record_dither = s; }
+ void setRecordPeriod(int ms);
+ void setRecordFile(const QString&);
+ void setRecordArgs(const QStringList&);
+ int recordPeriod() const { return record_period; }
+ void setRecording(bool on);
+ bool isRecording() const { return recordTimer.isActive(); }
+ void setAutoRecord(int from, int to);
+ void setDeviceKeys(bool);
+ void setCacheEnabled(bool);
+ void addLibraryPath(const QString& lib);
+
+ QMenuBar *menuBar() const;
+
+public slots:
+ void sceneResized(QSize size);
+ void openQml(const QString& fileName);
+ void open();
+ void reload();
+ void takeSnapShot();
+ void toggleRecording();
+ void toggleRecordingWithSelection();
+ void ffmpegFinished(int code);
+ void setSkin(const QString& skinDirectory);
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void timerEvent(QTimerEvent *);
+
+ void createMenu(QMenuBar *menu, QMenu *flatmenu);
+
+private slots:
+ void setScaleSkin();
+ void setScaleView();
+
+private:
+ QString currentFileName;
+ PreviewDeviceSkin *skin;
+ QSize skinscreensize;
+ QFxView *canvas;
+ void init(QFxTestEngine::TestMode, const QString &, const QString& fileName);
+ QBasicTimer recordTimer;
+ QList<QImage*> frames;
+ QProcess* frame_stream;
+ QBasicTimer autoStartTimer;
+ QTime autoTimer;
+ QString record_dither;
+ QString record_file;
+ QStringList record_args;
+ int record_period;
+ int record_autotime;
+ bool devicemode;
+ QAction *recordAction;
+ QString currentSkin;
+ bool scaleSkin;
+ mutable QMenuBar *mb;
+
+ QFxTestEngine *testEngine;
+};
+
+#endif
diff --git a/tools/qmlviewer/qmlviewer.pro b/tools/qmlviewer/qmlviewer.pro
new file mode 100644
index 0000000..08d2d2b
--- /dev/null
+++ b/tools/qmlviewer/qmlviewer.pro
@@ -0,0 +1,12 @@
+DESTDIR = ../../bin
+QT += declarative script network sql
+# Input
+HEADERS += qmlviewer.h
+SOURCES += main.cpp qmlviewer.cpp
+
+include($$QT_SOURCE_TREE/tools/shared/deviceskin/deviceskin.pri)
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+CONFIG += console
diff --git a/tools/tools.pro b/tools/tools.pro
index d034dcd..7caef83 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -24,6 +24,7 @@ mac {
embedded:SUBDIRS += kmap2qmap
+contains(QT_CONFIG, declarative):SUBDIRS += qmlviewer qmldebugger
contains(QT_CONFIG, dbus):SUBDIRS += qdbus
!wince*:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns
embedded: SUBDIRS += makeqpf